新建项目

This commit is contained in:
gitea committed 2023-04-29 09:09:12 +08:00
1 parent 5e2e890cfc
commit 633d9b872b
1351 files changed
+730564

No files matched your search

@@ -0,0 +1,423 @@
/*
============================================================================
Name : 2048.c
Author : Maurits van der Schee
Description : Console version of the game "2048" for GNU/Linux
============================================================================
*/
#define _XOPEN_SOURCE 500
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
#include "shell.h"
#define printf(...) shellPrint(shell2048, ##__VA_ARGS__)
#define getchar() shellGetChar(shell2048)
#define SIZE 4
uint32_t score=0;
uint8_t scheme=0;
Shell *shell2048 = NULL;
char shellGetChar(Shell *shell) {
char data;
if (shell->read && shell->read(&data, 1) == 1) {
return data;
} else {
return -1;
}
}
void sleep(int ms) {
int time = SHELL_GET_TICK();
while (SHELL_GET_TICK() - time < ms) ;
}
void getColor(uint8_t value, char *color, size_t length) {
uint8_t original[] = {8,255,1,255,2,255,3,255,4,255,5,255,6,255,7,255,9,0,10,0,11,0,12,0,13,0,14,0,255,0,255,0};
uint8_t blackwhite[] = {232,255,234,255,236,255,238,255,240,255,242,255,244,255,246,0,248,0,249,0,250,0,251,0,252,0,253,0,254,0,255,0};
uint8_t bluered[] = {235,255,63,255,57,255,93,255,129,255,165,255,201,255,200,255,199,255,198,255,197,255,196,255,196,255,196,255,196,255,196,255};
uint8_t *schemes[] = {original,blackwhite,bluered};
uint8_t *background = schemes[scheme]+0;
uint8_t *foreground = schemes[scheme]+1;
if (value > 0) while (value--) {
if (background+2<schemes[scheme]+sizeof(original)) {
background+=2;
foreground+=2;
}
}
snprintf(color,length,"\033[38;5;%d;48;5;%dm",*foreground,*background);
}
void drawBoard(uint8_t board[SIZE][SIZE]) {
uint8_t x,y;
char color[40], reset[] = "\033[m";
printf("\033[H");
printf("2048.c %17d pts\n\n",score);
for (y=0;y<SIZE;y++) {
for (x=0;x<SIZE;x++) {
getColor(board[x][y],color,40);
printf("%s",color);
printf(" ");
printf("%s",reset);
}
printf("\n");
for (x=0;x<SIZE;x++) {
getColor(board[x][y],color,40);
printf("%s",color);
if (board[x][y]!=0) {
char s[8];
snprintf(s,8,"%u",(uint32_t)1<<board[x][y]);
uint8_t t = 7-strlen(s);
printf("%*s%s%*s",t-t/2,"",s,t/2,"");
} else {
printf(" · ");
}
printf("%s",reset);
}
printf("\n");
for (x=0;x<SIZE;x++) {
getColor(board[x][y],color,40);
printf("%s",color);
printf(" ");
printf("%s",reset);
}
printf("\n");
}
printf("\n");
printf(" ←,↑,→,↓ or q \n");
printf("\033[A"); // one line up
}
uint8_t findTarget(uint8_t array[SIZE],uint8_t x,uint8_t stop) {
uint8_t t;
// if the position is already on the first, don't evaluate
if (x==0) {
return x;
}
for(t=x-1;;t--) {
if (array[t]!=0) {
if (array[t]!=array[x]) {
// merge is not possible, take next position
return t+1;
}
return t;
} else {
// we should not slide further, return this one
if (t==stop) {
return t;
}
}
}
// we did not find a
return x;
}
bool slideArray(uint8_t array[SIZE]) {
bool success = false;
uint8_t x,t,stop=0;
for (x=0;x<SIZE;x++) {
if (array[x]!=0) {
t = findTarget(array,x,stop);
// if target is not original position, then move or merge
if (t!=x) {
// if target is zero, this is a move
if (array[t]==0) {
array[t]=array[x];
} else if (array[t]==array[x]) {
// merge (increase power of two)
array[t]++;
// increase score
score+=(uint32_t)1<<array[t];
// set stop to avoid double merge
stop = t+1;
}
array[x]=0;
success = true;
}
}
}
return success;
}
void rotateBoard(uint8_t board[SIZE][SIZE]) {
uint8_t i,j,n=SIZE;
uint8_t tmp;
for (i=0; i<n/2; i++) {
for (j=i; j<n-i-1; j++) {
tmp = board[i][j];
board[i][j] = board[j][n-i-1];
board[j][n-i-1] = board[n-i-1][n-j-1];
board[n-i-1][n-j-1] = board[n-j-1][i];
board[n-j-1][i] = tmp;
}
}
}
bool moveUp(uint8_t board[SIZE][SIZE]) {
bool success = false;
uint8_t x;
for (x=0;x<SIZE;x++) {
success |= slideArray(board[x]);
}
return success;
}
bool moveLeft(uint8_t board[SIZE][SIZE]) {
bool success;
rotateBoard(board);
success = moveUp(board);
rotateBoard(board);
rotateBoard(board);
rotateBoard(board);
return success;
}
bool moveDown(uint8_t board[SIZE][SIZE]) {
bool success;
rotateBoard(board);
rotateBoard(board);
success = moveUp(board);
rotateBoard(board);
rotateBoard(board);
return success;
}
bool moveRight(uint8_t board[SIZE][SIZE]) {
bool success;
rotateBoard(board);
rotateBoard(board);
rotateBoard(board);
success = moveUp(board);
rotateBoard(board);
return success;
}
bool findPairDown(uint8_t board[SIZE][SIZE]) {
bool success = false;
uint8_t x,y;
for (x=0;x<SIZE;x++) {
for (y=0;y<SIZE-1;y++) {
if (board[x][y]==board[x][y+1]) return true;
}
}
return success;
}
uint8_t countEmpty(uint8_t board[SIZE][SIZE]) {
uint8_t x,y;
uint8_t count=0;
for (x=0;x<SIZE;x++) {
for (y=0;y<SIZE;y++) {
if (board[x][y]==0) {
count++;
}
}
}
return count;
}
bool gameEnded(uint8_t board[SIZE][SIZE]) {
bool ended = true;
if (countEmpty(board)>0) return false;
if (findPairDown(board)) return false;
rotateBoard(board);
if (findPairDown(board)) ended = false;
rotateBoard(board);
rotateBoard(board);
rotateBoard(board);
return ended;
}
void addRandom(uint8_t board[SIZE][SIZE]) {
static bool initialized = false;
uint8_t x,y;
uint8_t r,len=0;
uint8_t n,list[SIZE*SIZE][2];
if (!initialized) {
srand(SHELL_GET_TICK());
initialized = true;
}
for (x=0;x<SIZE;x++) {
for (y=0;y<SIZE;y++) {
if (board[x][y]==0) {
list[len][0]=x;
list[len][1]=y;
len++;
}
}
}
if (len>0) {
r = rand()%len;
x = list[r][0];
y = list[r][1];
n = (rand()%10)/9+1;
board[x][y]=n;
}
}
void initBoard(uint8_t board[SIZE][SIZE]) {
uint8_t x,y;
for (x=0;x<SIZE;x++) {
for (y=0;y<SIZE;y++) {
board[x][y]=0;
}
}
addRandom(board);
addRandom(board);
drawBoard(board);
score = 0;
}
// int test() {
// uint8_t array[SIZE];
// // these are exponents with base 2 (1=2 2=4 3=8)
// uint8_t data[] = {
// 0,0,0,1, 1,0,0,0,
// 0,0,1,1, 2,0,0,0,
// 0,1,0,1, 2,0,0,0,
// 1,0,0,1, 2,0,0,0,
// 1,0,1,0, 2,0,0,0,
// 1,1,1,0, 2,1,0,0,
// 1,0,1,1, 2,1,0,0,
// 1,1,0,1, 2,1,0,0,
// 1,1,1,1, 2,2,0,0,
// 2,2,1,1, 3,2,0,0,
// 1,1,2,2, 2,3,0,0,
// 3,0,1,1, 3,2,0,0,
// 2,0,1,1, 2,2,0,0
// };
// uint8_t *in,*out;
// uint8_t t,tests;
// uint8_t i;
// bool success = true;
// tests = (sizeof(data)/sizeof(data[0]))/(2*SIZE);
// for (t=0;t<tests;t++) {
// in = data+t*2*SIZE;
// out = in + SIZE;
// for (i=0;i<SIZE;i++) {
// array[i] = in[i];
// }
// slideArray(array);
// for (i=0;i<SIZE;i++) {
// if (array[i] != out[i]) {
// success = false;
// }
// }
// if (success==false) {
// for (i=0;i<SIZE;i++) {
// printf("%d ",in[i]);
// }
// printf("=> ");
// for (i=0;i<SIZE;i++) {
// printf("%d ",array[i]);
// }
// printf("expected ");
// for (i=0;i<SIZE;i++) {
// printf("%d ",in[i]);
// }
// printf("=> ");
// for (i=0;i<SIZE;i++) {
// printf("%d ",out[i]);
// }
// printf("\n");
// break;
// }
// }
// if (success) {
// printf("All %u tests executed successfully\n",tests);
// }
// return !success;
// }
int main_2048(int argc, char *argv[]) {
uint8_t board[SIZE][SIZE];
char c;
bool success;
shell2048 = shellGetCurrent();
if (!shell2048) {
return -1;
}
// if (argc == 2 && strcmp(argv[1],"test")==0) {
// return test();
// }
if (argc == 2 && strcmp(argv[1],"blackwhite")==0) {
scheme = 1;
}
if (argc == 2 && strcmp(argv[1],"bluered")==0) {
scheme = 2;
}
printf("\033[?25l\033[2J");
initBoard(board);
while (true) {
c=getchar();
if (c == -1){
printf("\nError! Cannot read keyboard input!");
break;
}
switch(c) {
case 97: // 'a' key
case 104: // 'h' key
case 68: // left arrow
success = moveLeft(board); break;
case 100: // 'd' key
case 108: // 'l' key
case 67: // right arrow
success = moveRight(board); break;
case 119: // 'w' key
case 107: // 'k' key
case 65: // up arrow
success = moveUp(board); break;
case 115: // 's' key
case 106: // 'j' key
case 66: // down arrow
success = moveDown(board); break;
default: success = false;
}
if (success) {
drawBoard(board);
sleep(150);
addRandom(board);
drawBoard(board);
if (gameEnded(board)) {
printf(" GAME OVER \n");
break;
}
}
if (c=='q') {
printf(" QUIT? (y/n) \n");
c=getchar();
if (c=='y') {
break;
}
drawBoard(board);
}
if (c=='r') {
printf(" RESTART? (y/n) \n");
c=getchar();
if (c=='y') {
initBoard(board);
}
drawBoard(board);
}
}
printf("\033[?25h\033[m");
return EXIT_SUCCESS;
}
@@ -0,0 +1,27 @@
/**
* @file game.c
* @author Letter
* @brief game
* @version 0.1
* @date 2021-07-18
*
* @copyright (c) 2021 Letter
*
*/
#include "shell_cmd_group.h"
extern int main_2048(int argc, char *argv[]);
extern int main_pushbox(int argc, char* argv[]);
ShellCommand gameGroup[] =
{
SHELL_CMD_GROUP_ITEM(SHELL_TYPE_CMD_MAIN, 2048, main_2048,
game 2048\n2048 [param]\nParam: blackwhite bluered or null),
SHELL_CMD_GROUP_ITEM(SHELL_TYPE_CMD_MAIN,
pushbox, main_pushbox, game pushbox),
SHELL_CMD_GROUP_END()
};
SHELL_EXPORT_CMD_GROUP(
SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN,
game, gameGroup, games);
@@ -0,0 +1,183 @@
#include "shell.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define printf(...) shellPrint(shellPushbox, ##__VA_ARGS__)
#define getchar() shellGetChar(shellPushbox)
Shell *shellPushbox = NULL;
static char shellGetChar(Shell *shell) {
char data;
if (shell->read && shell->read(&data, 1) == 1) {
return data;
} else {
return -1;
}
}
//地图7行8列 行[0-6] 列[0-7]
//0 路
//1 墙
//2 箱子
//3 终点
//4 小老鼠
//7 小老鼠站在终止上
//5 箱子到达终点上
int g_boards[7][8] = {
{ 0, 1, 1, 1, 1, 1, 1, 0 },
{ 0, 1, 0, 0, 0, 0, 1, 1 },
{ 1, 3, 0, 1, 1, 2, 0, 1 },
{ 1, 0, 3, 3, 2, 0, 0, 1 },
{ 1, 0, 0, 1, 2, 0, 0, 1 },
{ 1, 0, 0, 4, 0, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 0, 0, 0 }
},
boards[7][8] = {};
//记录小老鼠在移动中的位置
int row = 0;
int col = 0;
int cnt = 0; //箱子个数,用来判断游戏是否结束。
//初始化地图
void pushbox_init()
{
for (int i = 0; i < 7 * 8; i++) { //这里是为了当你按下enter键时,能够重置游戏,重置游戏时需要重新初始化地图
boards[i / 8][i % 8] = g_boards[i / 8][i % 8];
if (4 == boards[i / 8][i % 8]) //这里还需要记录老鼠的位置
{
row = i / 8;
col = i % 8;
}
}
}
//打印地图
void pushbox_print_map()
{
printf( "\r\n LetterShell PushBox!\r\n");
for (int i = 0; i < 7; i++) {
printf( " ");
for (int j = 0; j < 8; j++) {
switch (boards[i][j]) {
case 0:
printf( " ");
break; //空格代表路径
case 1:
printf( "■");
break; //打印墙
case 2:
case 5:
printf( "●");
break; //打印箱子
case 3:
printf( "★");
break; //打印终点
case 4:
case 7:
printf( "♀");
break; //打印小老鼠
}
}
printf( "\r\n");
}
printf("w,a,s,d or q\n");
}
//推箱子
int pushbox_print_move(int nrow, int ncol, int nnrow, int nncol)
{
printf( "\033[H");
if (0 == boards[nrow][ncol] || 3 == boards[nrow][ncol]) //如果小老鼠前面是路或者终点,说明可以移动
{
boards[nrow][ncol] += 4; //小老鼠进入这个位置了
boards[row][col] -= 4; //小老鼠离开这个位置了
//移动过后小老鼠的位置也改变了
row = nrow;
col = ncol;
} else if (2 == boards[nrow][ncol] || 5 == boards[nrow][ncol]) //如果小老鼠前面是箱子
{
if (0 == boards[nnrow][nncol] || 3 == boards[nnrow][nncol]) //如果箱子前面是路或者终点则可以移动
{
boards[nnrow][nncol] += 2;
boards[nrow][ncol] -= 2 - 4;
//这里其实是boards[nrow][ncol]=boards[nrow][ncol]-2+4
//减去2是因为箱子移走了,加上4是因为小老鼠进入了
boards[row][col] -= 4;
row = nrow;
col = ncol;
}
}
for (int i = 0; i < 7; i++) //统计游戏是否结束,当箱子都在终点上时就结束了
{
for (int j = 0; j < 8; j++) {
if (5 == boards[i][j]) {
cnt++;
}
if (3 == cnt) {
printf( "通关!\r\n");
return 1; //通关退出游戏
}
}
}
cnt = 0; //如果游戏没有结束,下次还是需要从0统计
pushbox_print_map();
return 0;
}
int main_pushbox(int argc, char* argv[])
{
char c;
int res = 0;
shellPushbox = shellGetCurrent();
if (!shellPushbox) {
return -1;
}
printf( "\033[?25l\033[2J");
printf( "\033[H");
pushbox_init();//游戏初始化
pushbox_print_map();
while (1) {
c = getchar();;
if (c < 0) {
printf("\nError! Cannot read keyboard input!");
break;
}
switch (c) //每次都需要判断小老鼠前面和前面的前面的坐标的状态,这样可以在move()
{ //函数中统一各个方向的写法
case 'w':
res = pushbox_print_move(row - 1, col, row - 2, col);
break;
case 's':
res = pushbox_print_move(row + 1, col, row + 2, col);
break;
case 'a':
res = pushbox_print_move(row, col - 1, row, col - 2);
break;
case 'd':
res = pushbox_print_move(row, col + 1, row, col + 2);
break;
case 'r':
pushbox_init();
break; //按enter则从新开始游戏
case 'q':
res = 1; //如果按q则退出游戏
}
if(res){
break;
}
}
printf( "\033[?25l\033[2J");
return EXIT_SUCCESS;
}
@@ -0,0 +1,14 @@
# game
![version](https://img.shields.io/badge/version-1.0.0-brightgreen.svg)
![standard](https://img.shields.io/badge/standard-c99-brightgreen.svg)
![build](https://img.shields.io/badge/build-2021.07.18-brightgreen.svg)
![license](https://img.shields.io/badge/license-MIT-brightgreen.svg)
## 简介
这是一个仅供娱乐的组件,移植了几个命令行的游戏
| 游戏 | 来源 |
| ---- | ------------------------------------------------ |
| 2048 | [mevdschee/2048](https://github.com/mevdschee/2048.c) |