Bootstrap

2048小游戏【C语言版】单文件编写

设计思路

  1. 游戏地图和初始设置
    • 使用一个 4x4 的二维数组 map 来表示游戏地图。
    • 初始时,所有位置的值均为 0。
    • score 记录玩家得分,move_num 记录移动次数。
  2. 随机生成数字
    • 在地图上随机选择一个空位置生成 2 或 4。
    • 只有在地图发生变化时才会生成新数字。
  3. 游戏菜单
    • 使用 menu() 函数显示当前的游戏状态,包括地图、得分和移动次数。
    • 提示玩家使用 W、A、S、D 键进行移动。
  4. 玩家移动
    • 使用 move() 函数读取玩家输入,并根据输入的方向调用相应的移动函数 (up()left()down()right())。
    • 每个移动函数都负责处理特定方向的移动,并更新地图。
  5. 移动逻辑
    • 移动时首先合并相同的数字,然后将非零元素向目标方向移动填补空格。
    • change 变量用于记录地图是否发生变化,以决定是否生成新数字。
  6. 游戏结束判断
    • 使用 over() 函数检查游戏是否结束。
    • 游戏结束的条件是:地图没有空位且没有相邻的相同数字。
    • 若游戏结束,输出最终得分和移动次数。

细节分析

  • 随机数生成:使用 rand() 函数生成随机位置和数字,但未处理随机数种子的初始化位置,可能会导致每次运行的结果相同。
  • 输入处理:使用 getch() 函数获取用户输入,并根据输入调用相应的移动函数。
  • 移动实现:每个方向的移动函数都按照特定的顺序检查并合并相同的数字,然后移动非零元素。
  • 游戏结束检测:遍历整个地图,检查是否还有空位或相邻的相同数字。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h> // 用于 getch 函数

int map[4][4] = {0}; // 游戏地图
int score = 0;       // 玩家得分
int move_num = -1;   // 移动次数
int game_over = 1;   // 游戏结束标志,0表示游戏结束
int change = 1;      // 跟踪地图是否发生变化,0表示没有变化
char input;          // 控制方向

// 函数声明
void start();
void randIntNum();
void menu();
void move();
int up();
int left();
int down();
int right();
int over();

// 在数组中随机生成一个位置并赋值2或4
void randIntNum()
{
    int i, j, n;
    if (change >= 1) // 只有在地图变化时才生成新数字
    {
        do
        {
            i = rand() % 4; // 随机行索引
            j = rand() % 4; // 随机列索引
        } while (map[i][j] != 0); // 确保位置为空

        n = rand() % 2;               // 随机选择0或1
        map[i][j] = (n == 0) ? 2 : 4; // 将2或4赋值给选中的位置

        move_num++; // 增加移动计数
    }
}

// 显示游戏菜单
void menu()
{
    system("cls"); // 清屏
    int i, j;
    printf("                 欢迎来到2048\n");
    printf("     ----------------------------------------\n");
    printf("     W——UP S——DOWN A——LEFT D——RIGHT\n");
    printf("     请按0退出游戏。\n");
    printf("     MOVE:%d          SCORE:%d\n", move_num, score);
    printf("     \n     |-------------------------------------------|\n");
    for (i = 0; i <= 3; i++)
    {
        for (j = 0; j <= 3; j++)
        {
            printf("     ");
            if (map[i][j] == 0)
                printf("|     ");
            else
                printf("|%5d", map[i][j]);
        }
        printf("     |\n     |-------------------------------------------|\n");
    }
}

// 处理玩家的移动
void move()
{
    char ch = getch(); // 从键盘读取控制输入
    change = 0;        // 重置变化跟踪器
    switch (ch)
    {
    case '0':                            // 如果玩家输入'0'
        printf("确定要退出吗?(y/n)\n"); // 确认退出
        ch = getchar();
        if (ch == 'y' || ch == 'Y') // 如果是,退出游戏
            exit(0);
        break;
    case 'w': // 上移
    case 'W':
        up();
        break;
    case 'a': // 左移
    case 'A':
        left();
        break;
    case 's': // 下移
    case 'S':
        down();
        break;
    case 'd': // 右移
    case 'D':
        right();
        break;
    default: // 无效输入
        printf("无效输入,请重新输入!\n");
        break;
    }
}

// 向上移动
int up()
{
    int now, next;
    int i, j, k;
    for (j = 0; j < 4; j++)
    {
        for (i = 0; i < 4; i++)
        {
            now = map[i][j];
            {
                k = i + 1;
                while (k < 4)
                {
                    next = map[k][j];
                    if (next != 0)
                    {
                        if (now == next)
                        {
                            change = 1;
                            score += map[k][j] * 2;
                            map[i][j] = 2 * map[k][j];
                            map[k][j] = 0;
                        }
                        k = 4;
                    }
                    k++;
                }
            }
        }
    }
    // 将非零元素向上移动,填补空格
    for (j = 0; j < 4; j++)
    {
        for (i = 0; i < 4; i++)
        {
            now = map[i][j];
            if (now == 0)
            {
                k = 1 + i;
                while (k < 4)
                {
                    next = map[k][j];
                    if (next != 0)
                    {
                        change = 1;
                        map[i][j] = next;
                        map[k][j] = 0;
                        k = 4;
                    }
                    k++;
                }
            }
        }
    }
    return change;
}

// 向右移动
int right()
{
    int i, j;
    int now, next, k;
    for (i = 0; i < 4; i++)
    {
        for (j = 3; j >= 0; j--)
        {
            now = map[i][j];
            k = j - 1;
            while (k >= 0)
            {
                next = map[i][k];
                if (next != 0)
                {
                    if (next == now)
                    {
                        change = 1;
                        score += map[i][k] * 2;
                        map[i][j] = map[i][k] * 2;
                        map[i][k] = 0;
                    }
                    k = -1;
                }
                k--;
            }
        }
    }
    // 将非零元素向右移动,填补空格
    for (i = 0; i < 4; i++)
    {
        for (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;
}

// 向左移动
int left()
{
    int i, j;
    int now, next, k;
    for (i = 0; i < 4; i++)
    {
        for (j = 0; j < 4; j++)
        {
            now = map[i][j];
            k = j + 1;
            while (k < 4)
            {
                next = map[i][k];
                if (next != 0)
                {
                    if (now == next)
                    {
                        change = 1;
                        score += 2 * map[i][k];
                        map[i][j] = map[i][k] * 2;
                        map[i][k] = 0;
                    }
                    k = 4;
                }
                k++;
            }
        }
    }
    // 将非零元素向左移动,填补空格
    for (i = 0; i < 4; i++)
    {
        for (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 down()
{
    int i, j;
    int now, next, k;
    for (j = 0; j < 4; j++)
    {
        for (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 (now == next)
                        {
                            change = 1;
                            score += map[k][j] * 2;
                            map[i][j] = map[k][j] * 2;
                            map[k][j] = 0;
                        }
                        k = -1;
                    }
                    k--;
                }
            }
        }
    }
    // 将非零元素向下移动,填补空格
    for (j = 0; j < 4; j++)
    {
        for (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 over()
{
    // 检查游戏是否结束
    game_over = 0;

    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            //判断地图里是否还有空位
            if (map[i][j] == 0)
            {
                game_over = 1;
                break;
            }

            //判断是否有相同的两个数字挨在一起,若有则gameover改为1,
            if (i > 1)
            {
                if (map[i][j] == map[i - 1][j])
                    game_over = 1;
                break;
            }

            if (j > 1)
            {
                if (map[i][j] == map[i][j - 1])
                {
                    game_over = 1;
                    break;
                }
            }
        }

        if (game_over == 1)
            break;
    }

    if (game_over == 0) // 游戏结束
    {
        printf("游戏结束!\n最终得分:%d\n", score);
        printf("移动次数:%d\n", move_num);
    }
}
// 游戏开始函数
void start()
{
    srand((unsigned)time(NULL)); // 初始化随机数生成器

    while (game_over) // 游戏循环
    {
        randIntNum(); // 在随机位置生成初始数字
        menu();       // 显示菜单
        move();       // 处理玩家输入和移动
        over();
    }
}

int main()
{
    start(); // 开始游戏
    return 0;
}
;