前言:

突然想写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循环:

    • 向下

代码如下:

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

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是没有用的,只能按上下左

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

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐