C的简单新手小游戏练习,知识基本是数组,用到指针的比较少,代码含有少量简单的C++,个人认为2048的核心是数字的移动与合并,其次是玩家有效操作的判断,与井字棋有点像。
代码实现了2048的基本功能,数字移动、合并、随机数产生在随机空白位置、有效操作判定、步数记录、得分情况、放弃本局游戏,以及通过修改宏定义常量值能玩更大的棋盘。如果加入文件的读写应该可以多一个排行榜功能。
目前存在情况是随着数字的位数增加界面框会歪斜,以及在游戏菜单界面输入字母直接退出。
代码如下
game.h 文件 #pragma once #include#include #include #include using namespace std; #define ROW 4 #define COL 4 extern void Intialize(int (*p)[COL]); extern void Checkerboard(int (*p)[COL]); extern void Random(int (*p)[COL],int k); extern void MoveAss(int(*p)[COL], int i, int j,char o); //extern void Valid(int(*p)[COL],char o,char q,int* g); //extern void Valid(int(*p)[COL], char o, int q); extern int Move(int(*p)[COL], char o); extern void Operate(int (*p)[COL],int k,int* c,int* g); extern int Criterion(int (*p)[COL]); extern void Progress(int (*p)[COL]); game.cpp 文件 #include "game.h" //界面初始化 void Intialize(int (*p)[COL]) { int i = 0; int j = 0; for (i = 0; i < ROW; i++)//遍历 { for (j = 0; j < COL; j++) p[i][j] = 0; } } //打印界面 void Checkerboard(int (*p)[COL]) { int i = 0; int j = 0; for (i = 0; i < ROW; i++) { for (j = 0; j < COL; j++) { if (j == COL - 1) { if (p[i][j]) cout << ' ' << p[i][j]; else cout << ' ' << ' ';//掩盖 0 } else { if (p[i][j]) cout << ' ' << p[i][j] << ' ' << '|';//打印 p[][] | 单元 else cout << ' ' << ' ' << ' ' << '|';//掩盖 0 } } cout << endl; for (j = 0; j < COL; j++) { if (i != ROW-1) cout << "----";//打印 --- 单元 if (j == COL - 1) cout << endl; } } cout << endl; } //在界面随机生成一个2/4数字 void Random(int (*p)[COL],int k) { int x = 0; int y = 0; if (k != 2048) { if (k) { while (1)//生成一个随机数 { x = rand() % ROW; y = rand() % COL; if (p[x][y] == 0)//寻找空位 { p[x][y] =(rand() % 2 + 1) * 2; break;//(rand()%2+1)*2随机生成2/4数字 } } } if (k != ROW * COL) Checkerboard(p);//在界面上显示 } } //辅助移动 void MoveAss(int(*p)[COL],int i,int j,char o) { switch (o) { case 'w': { if (p[i][j]) { if ((i != 0)&&(i <= ROW-1)) { if (p[i - 1][j] == 0) { p[i - 1][j] = p[i][j]; p[i][j] = 0; MoveAss(p, i + 1, j, o);//递归调用 } } } break; } case 's': { if (p[i][j]) { if ((i != ROW-1)&&(i >= 0)) { if (p[i + 1][j] == 0) { p[i + 1][j] = p[i][j]; p[i][j] = 0; MoveAss(p, i - 1, j, o);//递归调用 } } } break; } case 'a': { if (p[i][j]) { if ((j != 0)&&(j <= COL - 1)) { if (p[i][j - 1] == 0) { p[i][j - 1] = p[i][j]; p[i][j] = 0; MoveAss(p, i, j + 1, o);//递归调用 } } } break; } case 'd': { if (p[i][j]) { if ((j != ROW - 1)&&(j >= 0)) { if (p[i][j + 1] == 0) { p[i][j + 1] = p[i][j]; p[i][j] = 0; MoveAss(p, i, j - 1, o);//递归调用 } } } break; } } } //数字移动与合并 int Move(int (*p)[COL],char o) { int i = 0; int j = 0; int g = 0; switch (o) { case 'w': { for (i = ROW - 1; i >= 0; i--)//移动 { for (j = COL - 1; j >= 0; j--) { MoveAss(p, i, j, o); } } for (i = 0; i < ROW-1; i++)//合并 { for (j = 0; j < COL; j++) { if (p[i][j] == p[i + 1][j]) { p[i][j] = 2 * p[i][j]; g = g + p[i][j]; p[i + 1][j] = 0; } } } for (i = ROW - 1; i >= 0; i--)//移动 { for (j = COL - 1; j >= 0; j--) MoveAss(p,i,j,o); } break; } case 's': { for (i = 0; i < ROW; i++)//移动 { for (j = 0; j < COL; j++) { MoveAss(p, i, j, o); } } for (i = ROW-1; i > 0; i--)//合并 { for (j = 0; j < COL; j++) { if (p[i][j] == p[i - 1][j]) { p[i][j] = 2 * p[i][j]; g = g + p[i][j]; p[i - 1][j] = 0; } } } for (i = 0; i < ROW; i++)//移动 { for (j = 0; j < COL; j++) MoveAss(p, i, j, o); } break; } case 'a': { for (j = COL - 1; j >= 0; j--)//移动 { for (i = ROW - 1; i >= 0; i--) { MoveAss(p, i, j, o); } } for (j = 0; j < COL - 1; j++)//合并 { for (i = 0; i < ROW; i++) { if (p[i][j] == p[i][j + 1]) { p[i][j] = 2 * p[i][j]; g = g + p[i][j]; p[i][j + 1] = 0; } } } for (j = COL - 1; j >= 0; j--)//移动 { for (i = ROW - 1; i >= 0; i--) MoveAss(p, i, j, o); } break; } case 'd': { for (j = 0; j < COL; j++)//移动 { for (i = 0; i < ROW; i++) { MoveAss(p, i, j, o); } } for (j = COL-1; j > 0; j--)//合并 { for (i = 0; i < ROW; i++) { if (p[i][j] == p[i][j - 1]) { p[i][j] = 2 * p[i][j]; g = g + p[i][j]; p[i][j - 1] = 0; } } } for (j = 0; j < COL; j++)//移动 { for (i = 0; i < ROW; i++) MoveAss(p, i, j, o); } break; } } return g; } //有效移动判定 int Valid(int (*p)[COL],char o,char q,int* g)//重载,通过参数为字符还是整形来调用同名的不同函数 { int arr1[ROW][COL]; int i = 0; int j = 0; int v = 0; for (i = 0; i < ROW; i++)//拷贝一份 { for (j = 0; j < COL; j++) { arr1[i][j] = p[i][j]; } } *g = *g + Move(p, o); for (i = 0; i < ROW; i++) { for (j = 0; j < COL; j++) { if (arr1[i][j] != p[i][j]) { v = 1; break; } } if (v == 1) break; } return v; } int Valid(int(*p)[COL], char o,int q)//重载,通过参数为字符还是整形来调用同名的不同函数 { int arr1[ROW][COL]; int i = 0; int j = 0; int v = 0; for (i = 0; i < ROW; i++)//拷贝一份 { for (j = 0; j < COL; j++) { arr1[i][j] = p[i][j]; } } Move(arr1, o); for (i = 0; i < ROW; i++) { for (j = 0; j < COL; j++) { if (arr1[i][j] != p[i][j]) { v = 1; break; } } if (v == 1) break; } return v; } //玩家操作 void Operate(int (*p)[COL],int* k,int* c,int* g) { char o = '0'; char ret[20]; while (1) { cout << "请输入:" << endl; cin >> ret; o = ret[0];//只读取输入的第一个字符 if (o == 'w' || o == 's' || o == 'a' || o == 'd') { if (Valid(p, o, 'q', g)) { *c = *c + 1; break; } else cout << "无效移动" << endl; } else if (o == '0') break; else cout << "输入错误" << endl; } if (o == '0') *k = -1; else Checkerboard(p); } //游戏结束判定 int Criterion(int (*p)[COL]) { int i = 0; int j = 0; int k = COL * ROW;//空格剩余数 for (i = 0; i < ROW; i++) { for (j = 0; j < COL; j++) { if (p[i][j] == 2048)//胜利 { k = 2048; break; } if (p[i][j] != 0) k--; } if (k == 2048) break; } return k; } //控制游戏进程 void Progress(int (*p)[COL]) { int k = ROW * COL;//初始空格数 int count = 0; int grade = 0; Random(p,k); while(1) { k = Criterion(p); Random(p,k); if ((k > 0) && (k != 2048)) k = k - 1; if (k == 2048) { cout << "恭喜,你赢了!" << endl; break; } if (k == 0) { if ((Valid(p, 'w',1) || Valid(p, 's',1) || Valid(p, 'a',1) || Valid(p, 'd',1)) == 0) { cout << "很遗憾,你输了。" << endl; break; } } Operate(p, &k,&count,&grade); if (k == -1) { cout << "已放弃当前游戏。" << endl; break; } cout << "步数: " << count << " "; cout << "分数: " << grade << endl << endl; } } test.cpp 文件 #include "game.h" void nume() { cout << endl; cout << "*****************************" << endl; cout << "****** 2 0 4 8 *******" << endl; cout << "****** 1:paly *******" << endl; cout << "****** 0:exit *******" << endl; cout << "*****************************" << endl << endl; } void game() { int ARR[ROW][COL] = {0}; int (*p)[COL] = ARR; Intialize(p); //Checkerboard(p); Procgress(p); } void select() { int input = 0; do { nume(); srand((unsigned int)time(NULL)); cout << "请选择" << endl << endl; cin >> input; cout << endl; switch (input) { case 1: cout << "开始游戏" << endl << endl; cout << " w:上移 s:下移" << endl << endl; cout << " a:左移 d:右移" << endl << endl; cout << " 0:放弃当前游戏" << endl << endl; game(); break; case 0: cout << "退出" << endl; break; default: cout << "选择错误,请重新选择" << endl<



