前言:
突然想写2048,就模仿人家写的2048,写了2048,但有所改良😁(改良了一点小毛病,但绝大部分都一样)
一、编译器
我用的时vs2022的版本,其他版本没试过,但我估计devc++是可以的
二、2048的代码
- 头文件、全局变量
代码如下:
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include<conio.h> //提供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或4
menu(); //菜单以及棋盘
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就为4
if (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就为next
map[k][j] = 0; //next就应该为0
k = 4; //应该now已经被next的值占据,不可以在被其他值占据,所以退出while循环
}
k++; //如果下一个元素为0就在下一个
}
}
}
}
return change; 返回change,change是否等于1影响要不要在进行生成随机数
}
为什么需要两层for循环:
![](https://i-blog.csdnimg.cn/blog_migrate/9b0f72c58a868aa74f299e4806eecc10.png)
- 向下
代码如下:
与向上大同小异,就是向下需要从最后一行开始,向上遍历
int down() {
int now = 0, next = 0;
int k = 0;
for (int j = 0; j < 4; j++) {
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 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 < 4; j++) {
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) {
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 < 4; i++) {
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 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 < 4; i++) {
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) {
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 < 4; j++) {
if (map[i][j] == 0) { //还存在0就可以继续
gameover = 1;
}
if (i >= 1) { //i>=1是因为i-1要>=0
if (map[i][j] == map[i - 1][j]) { //如果上下相邻元素右相等的就继续
gameover = 1;
}
}
if (j >= 1) { //j>=1是因为j-1要>=0
if (map[i][j] == map[i][j - 1]) { //如果左右相邻元素右相等的就继续
gameover = 1;
}
}
}
}
}
三、总结
2048就这么多了,第一次随机数在边界(下图在右边),第一次按D是没有用的,只能按上下左
有什么好的解决方法可以提出来,不想 想了
![](https://i-blog.csdnimg.cn/blog_migrate/94b509493f68c2e485ac32fb2a97841f.png)