1. 最基本的要求
掌握if-else语句,循环,二维数组,函数。
2. 了解2048的游戏规则
规则如下:
每次可以选择上下左右其中一个方向去滑动,每滑动一次,所有的数字方块都会往滑动的方向靠拢,系统也会在空白的地方随机出现一个数字方块,2或4,相同数字的方块在靠拢时相加。玩家要想办法在这小小的16格范围中凑出“2048”这个数字方块。
3. 找到游戏的核心
很显然游戏的核心是控制移动:
怎样移动就要根据游戏规则来提炼条件,我们可以发现其实上下左右只要想出一个方向,其他三个方向也是信手拈来。搞定了移动就还剩下几个比较重要的:随机数的产生、剩余空值(这里指的是0)的统计、是否游戏结束的判断以及用二维数组来实现方块。
(随机数的产生、清屏、暂停这些基础c语言课程中不会学到,本菜鸡做的时候也是上了度娘又上知乎才学到的。接下来我也会单独强调的。)
最简易的2048如下图所示:
1. 4x4棋盘
用二维数组即可,如接下来你将会看到我用qq[4][4]来代表棋盘。
2. 移动
以向上移动为例:
void up(){ int i,j,k; for (i = 0; i < 4; i++) { k = 0; for(j = 1; j < 4;j++) //同一列中qq[j][i]在qq[k][i]下面 { if(qq[j][i] > 0) //判断qq[k][i]下面是否为零0数 { if (qq[j][i] == qq[k][i]) //判断两个数是否相同,相同就要合起来 { score += qq[k][i] *= 2; //分数累加,相同的加起来,使用*2也是一样的 qq[j][i] = 0; //合起来后原来下面这项qq[j][i]给了qq[k][i]所以本身要变为0 } else if (qq[k][i] == 0) //判断上面的这项是否为0 { qq[k][i] = qq[j][i]; //是 就直接换值 qq[j][i] = 0; } else //上面项与下面不等于0的项不相等同时上面项不等于零时 { qq[k+1][i] = qq[j][i]; //将下面项移到上面项的后一项 k++; if (k != j) //如果qq[j][i]本来就是qq[k][i]的后一项就相当于不移动值不变,就不执行令qq[j][i]等于0的指令 { qq[j][i] = 0; //qq[j][i]不是qq[k][i]后一项就移到它后一项同时原来的位置上的数变为0 } } } } }}
要将移动的条件理清楚,一个一个条件慢慢来,搞清楚是并列还是包含关系。
以 一列 为例
第一个判断条件可以表示成如下图所示:
第二、三个判断条件可以表示成如下图所示:
接下来的可以仿照这个上面两张图自己想一想,最好自己画个图理解其中的逻辑关系。
3. 重新开始游戏及随机数的基本格式
void restart(){ system("cls"); //清屏 printf(" ****2048****\n"); printf("由8上 2下 4左 6右控制,5重新开始,1退出游戏\n"); //提示消息 score = 0; //重置分数 int n = rand() % 16; //在0-15中随机取出一个数 int i,j; for (i = 0; i < 4; i++) //行数 { for (j = 0; j < 4; j++) //列数 { if (n-- == 0) //随机令一个二维数组中的等于2 { qq[i][j]=2; } else //除了一个等于2其他都等于0 { qq[i][j]=0; } printf("%5d",qq[i][j]); //5宽度输出 } printf("\n\n"); //两换行更美观 }}
产生随机数需要包含的头文件:
#include#include
C 库函数 void srand(unsigned int seed) 播种由函数 rand 使用的随机数发生器。它初始化随机种子,会提供一个种子,这个种子会对应一个随机数,如果使用相同的种子后面的 rand() 函数会出现一样的随机数。
srand((unsigned)time(0));//设置随机数种子(随机数类型)
number=rand();
一个都不能少
例如:i=rand()%N意思是在0到(N-1)之间随机取一个数
4. 统计空值的个数(作为产生随机数的范围及判断是否游戏结束)
int zero_number() //记录所剩0的个数{ int n,i,j; n = 0; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if (qq[i][j] == 0) { n++; //统计0的个数 } } }
5. 产生随机数
srand((int)time(0)); int i,j; int n = rand() % zero_number(); //产生一个0 到(剩几个零-1)的随机数 for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if(qq[i][j] == 2048) //判断是否胜利 { m = 2; } if (qq[i][j] == 0&& n-- == 0) //随机给一个位置上是0的赋值2或者4 { if (rand() % 3) //取个0-2的随机数,取到1,2都是赋2 , 0 是赋4,赋值2或者4的比例是2:1 { qq[i][j] = 2; } else { qq[i][j] = 4; } } printf("%5d",qq[i][j]); } printf("\n\n"); }
6. 判断游戏是否结束
int gameover() //判断数组中没0的时候相邻项是否相等{ int n,i,j; n = 1; //n作为判断条件 for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if (qq[i][j] == qq[i][j+1]|| qq[j][i] == qq[j+1][i]) //判断数组中相邻项是否相等 { n = 0; } } } return n;}
if (zero_number() == 0&& gameover()) //同时满足数组没有一个0且相邻的数不相等 { system("cls"); printf("游戏失败\n"); system("pause"); break; //游戏失败的出口 }
7. 游戏的主体控制部分begin函数、main函数和头文件
void begin() { for(;;) //无条件进入for循环 { system("cls"); printf(" ****2048****\n"); printf("由8上 2下 4左 6右控制,5重新开始,1退出游戏\n"); srand(time(0)); int i,j; int n = rand() % zero_number(); //产生一个0 到(剩几个零-1)的随机数 for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if(qq[i][j] == 2048) //判断是否胜利 { m = 2; } if (qq[i][j] == 0&& n-- == 0) //随机给一个位置上是0的赋值2或者4 { if (rand() % 3) //取个0-2的随机数,取到1,2都是赋2 , 0 是赋4,赋值2或者4的比例是2:1 { qq[i][j] = 2; } else { qq[i][j] = 4; } } printf("%5d",qq[i][j]); } printf("\n\n"); } int in = getch(); //获得控制键输入 switch (in) //控制上下左右,重新开始和退出游戏 { case '8' : up(); break; case '2' : down(); break; case '4' : left(); break; case '6' : right(); break; case '5' : restart(); break; case '1' : m = 1; break; default : ; } if (m == 1) //对了应1控制键退出游戏的出口 { break; } if (m == 2) //游戏胜利的出口 { system("cls"); printf("游戏胜利\n"); system("pause"); break; } if (zero_number() == 0&& gameover()) //同时满足数组没有一个0且相邻的数不相等 { system("cls"); printf("游戏失败\n"); system("pause"); break; //游戏失败的出口 } }}
void main(){ restart(); begin(); system("pause"); system("cls"); printf("得分为:%d\n欢迎下次在玩!!!",score); system("pause");}
#include #include #include //要用到随机数 #include //要用到清屏#include //要用到暂停void begin(); //游戏开始时的主要控制中心void restart(); //重新开始int gameover(); //判断是否失败int zero_number(); //二维数组中零的个数void up(); //向上移void down(); //向下移void left(); //向左移void right(); //向右移int qq[4][4]; //4*4的位置int score; //统计分数int m = 0; //m用来作判断条件
本人也是一个刚接触(零基础)c语言的菜鸡,对于这个游戏其实实际用时差不多用八个小时左右。本菜鸡是肝网课(循环、一维数组、函数、二维数组用1.5倍速)肝了一个晚自习(两个小时左右),构思了一个晚自习并且查找完了要用到的没学过的东西(随机数一类的东西),敲代码敲了一个上午(四个小时左右其中出现了很多初学者经常犯的错误可能是因为一直看网课实际操作不行)不断的调整和简化,虽然用的时间有点多,但是收获很多,增加了兴趣、巩固了知识以及开拓了思维。
对于刚接触c语言的老铁们有兴趣才有动力,而每一次打完代码编译运行没有丝毫问题我相信都会有一种成就觉,千万不要抗拒打代码。
祝各位代码越打越舒畅越打越六!!!
加油
最后附上代码:
#include #include #include //要用到随机数 #include //要用到清屏#include //要用到暂停void begin(); //游戏开始时的主要控制中心void restart(); //重新开始int gameover(); //判断是否失败int zero_number(); //二维数组中零的个数void up(); //向上移void down(); //向下移void left(); //向左移void right(); //向右移int qq[4][4]; //4*4的位置int score; //统计分数int m = 0; //m用来作判断条件void main(){ restart(); begin(); system("pause"); system("cls"); printf("得分为:%d\n欢迎下次在玩!!!",score); system("pause");}void restart(){ system("cls"); //清屏 printf(" ****2048****\n"); printf("由8上 2下 4左 6右控制,5重新开始,1退出游戏\n"); //提示消息 score = 0; //重置分数 int n = rand() % 16; //在0-15中随机取出一个数 int i,j; for (i = 0; i < 4; i++) //行数 { for (j = 0; j < 4; j++) //列数 { if (n-- == 0) //随机令一个二维数组中的等于2 { qq[i][j]=2; } else //除了一个等于2其他都等于0 { qq[i][j]=0; } printf("%5d",qq[i][j]); //5宽度输出 } printf("\n\n"); //两换行更美观 }}void begin() { for(;;) //无条件进入for循环 { system("cls"); printf(" ****2048****\n"); printf("由8上 2下 4左 6右控制,5重新开始,1退出游戏\n"); srand(time(0)); int i,j; int n = rand() % zero_number(); //产生一个0 到(剩几个零-1)的随机数 for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if(qq[i][j] == 2048) //判断是否胜利 { m = 2; } if (qq[i][j] == 0&& n-- == 0) //随机给一个位置上是0的赋值2或者4 { if (rand() % 3) //取个0-2的随机数,取到1,2都是赋2 , 0 是赋4,赋值2或者4的比例是2:1 { qq[i][j] = 2; } else { qq[i][j] = 4; } } printf("%5d",qq[i][j]); } printf("\n\n"); } int in = getch(); //获得控制键输入 switch (in) //控制上下左右,重新开始和退出游戏 { case '8' : up(); break; case '2' : down(); break; case '4' : left(); break; case '6' : right(); break; case '5' : restart(); break; case '1' : m = 1; break; default : ; } if (m == 1) //对了应1控制键退出游戏的出口 { break; } if (m == 2) //游戏胜利的出口 { system("cls"); printf("游戏胜利\n"); system("pause"); break; } if (zero_number() == 0&& gameover()) //同时满足数组没有一个0且相邻的数不相等 { system("cls"); printf("游戏失败\n"); system("pause"); break; //游戏失败的出口 } }}int zero_number() //记录所剩0的个数{ int n,i,j; n = 0; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if (qq[i][j] == 0) { n++; //统计0的个数 } } } return n;}int gameover() //判断数组中没0的时候相邻项是否相等{ int n,i,j; n = 1; //n作为判断条件 for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if (qq[i][j] == qq[i][j+1]|| qq[j][i] == qq[j+1][i]) //判断数组中相邻项是否相等 { n = 0; } } } return n;}void up(){ int i,j,k; for (i = 0; i < 4; i++) { k = 0; for(j = 1; j < 4;j++) //同一列中qq[j][i]在qq[k][i]下面 { if(qq[j][i] > 0) //判断qq[k][i]下面是否为零0数 { if (qq[j][i] == qq[k][i]) //判断两个数是否相同,相同就要合起来 { score += qq[k][i] *= 2; //分数累加,相同的加起来,使用*2也是一样的 qq[j][i] = 0; //合起来后原来下面这项qq[j][i]给了qq[k][i]所以本身要变为0 } else if (qq[k][i] == 0) //判断上面的这项是否为0 { qq[k][i] = qq[j][i]; //是 就直接换值 qq[j][i] = 0; } else //上面项与下面不等于0的项不相等同时上面项不等于零时 { qq[k+1][i] = qq[j][i]; //将下面项移到上面项的后一项 k++; if (k != j) //如果qq[j][i]本来就是qq[k][i]的后一项就相当于不移动值不变,就不执行令qq[j][i]等于0的指令 { qq[j][i] = 0; //qq[j][i]不是qq[k][i]后一项就移到它后一项同时原来的位置上的数变为0 } } } } }}void down(){ int i,j,k; for (i = 0 ; i < 4 ; i++) { k = 3; for (j = 2; j >= 0; j--) { if (qq[j][i] > 0) { if(qq[k][i] == qq[j][i]) { score += qq[k][i] *= 2; qq[j][i] = 0; } else if (qq[k][i] == 0) { qq[k][i] = qq[j][i]; qq[j][i] = 0; } else { qq[k-1][i] = qq[j][i]; k--; if (k != j) { qq[j][i] = 0; } } } } }}void left(){ int i,j,k; for (i = 0; i < 4; i++) { k = 0; for (j = 1; j < 4; j++) { if (qq[i][j] > 0) { if(qq[i][k] == qq[i][j]) { score += qq[i][k] *= 2; qq[i][j] = 0; } else if (qq[i][k] == 0) { qq[i][k] = qq[i][j]; qq[i][j] = 0; } else { qq[i][k+1] = qq[i][j]; k++; if (k != j) { qq[i][j] = 0; } } } } }}void right(){ int i,j,k; for (i = 0; i < 4; i++) { k = 3; for (j = 2; j >= 0; j--) { if (qq[i][j] > 0) { if(qq[i][k] == qq[i][j]) { score += qq[i][k] *= 2; qq[i][j] = 0; } else if (qq[i][k] == 0) { qq[i][k] = qq[i][j]; qq[i][j] = 0; } else { qq[i][k-1] = qq[i][j]; k--; if (k != j) { qq[i][j] = 0; } } } } }}
☆ END ☆