前言:

突然想写2048,就模仿人家写的2048,写了2048,但有所改良(改良了一点小毛病,但绝大部分都一样)

一、编译器

我用的时vs2022的版本,其他版本没试过,但我估计devc++是可以的

二、2048的代码

    • 头文件、全局变量

代码如下:

#include#include#include#include//提供getch()函数//全局变量int map[4][4] = { 0 }; //游戏地图int score = 0; //分数int movenum = -1; //移动次数char input; //控制方向int gameover = 1; //判断游戏是否结束,0结束int change = 1; //判断数组是否改变,0不变
    • main函数

代码如下:

int main(){text(); //转折一下//输了以后会打印以下内容printf(" Game Over\n");printf(" 你的得分为:%d\n", score);printf(" 你的移动次数为:%d\n", movenum);return 0;}
    • text()函数

代码如下:

void text(){srand((unsigned int)time(NULL));//设置随机数种子,(unsigned int) int看你们自己设置的类型while (gameover == 1) //当gameover=1时就继续,等于0时就结束了{RandInitNum();//在数组里随机寻找map[i][j]=0并赋值2或4menu();//菜单以及棋盘move();//移动over();//判断是否结束}}
    • 在数组里随机寻找map[i][j]=0并赋值2或4

代码如下:

void RandInitNum(){int i, j, n;if (change == 1) //一开始设置为1,进行第一次判断{//对i和j进行随机数分配do{i = ((unsigned int)rand()) % 4;j = ((unsigned int)rand()) % 4;} while (map[i][j] != 0);n = ((unsigned int)rand()) % 2; //n随机生成0或1,以便产生2或4,就是说当n=0时+2就为2,当n=1时+3就为4if (n == 0){map[i][j] = n + 2;}if (n == 1){map[i][j] = n + 3;}movenum++;//对地图赋值之后说明肯定对数组移动了,所以这里的步数加一。}}
    • 菜单以及棋盘

代码如下:

{//这里看起来没有对齐,但是vs经过编译后就是对齐的system("CLS");//每显示一次清屏之前的重新打印printf("*—*—*—*—*—*—*—*—*—*—*—*—*—*—*—*—*—*—*—*\n");printf("**W—上*S—下*A—左*D—右**\n");printf("** 退出游戏请按0,再次确定请按y**\n");printf("**移动次数:%d分数:%d **\n", movenum, score);printf("*—*—*—*—*—*—*—*—*—*—*—*—*—*—*—*—*—*—*—*\n");//打印棋盘printf("*———————————————*\n");for (int i = 0; i < 4; i++){printf("|");for (int j = 0; j < 4; j++){if(map[i][j]==0)//mao[i][j]=0时不打印{printf(" |");}else //map[i][j] != 0时打印map[i][j]{printf("%3d|", map[i][j]);}}printf("\n");printf("*———————————————*\n");}}
    • 进行上下左右的移动

#move()函数

代码如下:

void move(){input = _getch();//从键盘读取change = 0;switch (input){case'0'://退出游戏{printf("你是否想要退出?(y/n):");input = _getch();if (input == 'y' || input == 'Y'){printf("退出成功\n");exit(-1);}break;}case'w':case'W':{up();break;}case's':case'S':{down();break;}case'a':case'A':{left();break;}case'd':case'D':{right();break;}default:{printf("输入错误,请重新输入\n");break;}}}
    • 向上

代码如下:

int up() {int now = 0, next = 0; //now为所选的元素,next为now的下一个元素int k = 0;//第一个for语句是把当前控制方向的数组里相同的数合并,其他方向的都是一样初步对每一列的数进行合并for (int j = 0; j < 4;j++) { (列) for (int i = 0; i < 4; i++) { (行)now = map[i][j];if (now != 0) {//如果now不为0就判断now下面的元素是否有和now相等的元素,相等就加起来k = i + 1;//从now的下一个元素开始while (k < 4) {next = map[k][j];if (next != 0) {//下一个元素不等于0才可以进行比较if (now == next) {change = 1;score += map[k][j];//计分map[i][j] = 2 * map[k][j]; //相加后now就为之前的两倍map[k][j] = 0;//相加后next就要变为0}k = 4; 直接退出while循环,使用break也可以}k++;//如果下一个元素为0或者与now不相等就在下一个}}}//第二个for循环是对每一列的相等元素的最终合并,与第一个for循环一摸一样for (int i = 0; i < 4; i++) { //行now = map[i][j];if (now != 0) {k = i + 1;while (k < 4) {next = map[k][j];if (next != 0) {if (now == next) {change = 1;score += map[k][j];map[i][j] = 2 * map[k][j];map[k][j] = 0;}k = 4;}k++;}}}}//第三个for语句是把当前控制方向的非零元素移动当前方向的前面for (int j = 0; j < 4;j++) { (列)for (int i = 0; i < 4; i++) {(行) now = map[i][j]; if (now == 0) { //如果now为0,next不为0,就将next移动到now的位置k = i + 1;//从now的下一个元素开始while (k < 4) {next = map[k][j];if (next != 0) {change = 1;map[i][j] = next;//now就为nextmap[k][j] = 0; //next就应该为0k = 4; //应该now已经被next的值占据,不可以在被其他值占据,所以退出while循环}k++;//如果下一个元素为0就在下一个}}}}return change;返回change,change是否等于1影响要不要在进行生成随机数}

为什么需要两层for循环:

    • 向下

代码如下:

与向上大同小异,就是向下需要从最后一行开始,向上遍历

int down() {int now = 0, next = 0;int k = 0;for (int j = 0; j = 0; i--) {now = map[i][j];if (now != 0) {k = i - 1;while (k >= 0) {next = map[k][j];if (next != 0) {if (next == now) {change = 1;score += map[k][j];map[i][j] = map[k][j] * 2;map[k][j] = 0;}k = -1;}k--;}}}for (int i = 3; i >= 0; i--) {now = map[i][j];if (now != 0) {k = i - 1;while (k >= 0) {next = map[k][j];if (next != 0) {if (next == now) {change = 1;score += map[k][j];map[i][j] = map[k][j] * 2;map[k][j] = 0;}k = -1;}k--;}}}}for (int j = 0; j = 0; i--) {now = map[i][j];if (now == 0) {k = i - 1;while (k >= 0) {next = map[k][j];if (next != 0) {change = 1;map[i][j] = map[k][j];map[k][j] = 0;k = -1;}k--;}}}}return change;}
    • 向左

代码如下:

都差不多,第一层循环改为从行开始,第二层循环从列开始,因为是向左移动,是从第一列开始

int left() {int now = 0, next = 0;int k = 0;for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {now = map[i][j];if (now != 0) {k = j + 1;while (k < 4) {next = map[i][k];if (next != 0) {if (now == next) {change = 1;score += map[i][k];map[i][j] = map[i][k] * 2;map[i][k] = 0;}k = 4;}k++;}}}for (int j = 0; j < 4; j++) {now = map[i][j];if (now != 0) {k = j + 1;while (k < 4) {next = map[i][k];if (next != 0) {if (now == next) {change = 1;score += map[i][k];map[i][j] = map[i][k] * 2;map[i][k] = 0;}k = 4;}k++;}}}}for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {now = map[i][j];if (now == 0) {k = j + 1;while (k < 4) {next = map[i][k];if (next != 0) {change = 1;map[i][j] = map[i][k];map[i][k] = 0;k = 4;}k++;}}}}return change;}
    • 向右

代码如下:

都差不多,第一层循环改为从行开始,第二层循环从列开始,因为是向右移动,是从最后一列开始

int right() {int now = 0, next = 0;int k = 0;for (int i = 0; i = 0; j--) {now = map[i][j];if (now != 0) {k = j - 1;while (k >= 0) {next = map[i][k];if (next != 0) {if (next == now) {change = 1;score += map[i][k];map[i][j] = map[i][k] * 2;map[i][k] = 0;}k = -1;}k--;}}}for (int j = 3; j >= 0; j--) {now = map[i][j];if (now != 0) {k = j - 1;while (k >= 0) {next = map[i][k];if (next != 0) {if (next == now) {change = 1;score += map[i][k];map[i][j] = map[i][k] * 2;map[i][k] = 0;}k = -1;}k--;}}}}for (int i = 0; i = 0; j--) {now = map[i][j];if (now == 0) {k = j - 1;while (k >= 0) {next = map[i][k];if (next != 0) {change = 1;map[i][j] = map[i][k];map[i][k] = 0;k = -1;}k--;}}}}return change;}

7.判断是否结束

代码如下:

void over() {gameover = 0; //将gameover设置为0 如果以下循环不能使gameover变为1就结束游戏for (int i = 0; i < 4; i++) {for (int j = 0; j = 1) {//i>=1是因为i-1要>=0if (map[i][j] == map[i - 1][j]) {//如果上下相邻元素右相等的就继续gameover = 1;}}if (j >= 1) {//j>=1是因为j-1要>=0if (map[i][j] == map[i][j - 1]) {//如果左右相邻元素右相等的就继续gameover = 1;}}}}}

三、总结

2048就这么多了,第一次随机数在边界(下图在右边),第一次按D是没有用的,只能按上下左

有什么好的解决方法可以提出来,不想 想了