2048源码

自己写的一个控制台2048小游戏
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>  //提供 getch()
#include <windows.h>
#include <time.h> //提供 time() 用作随机数种子

int arr[4][4], copy[4][4]; //copy数组用于确认一次操作之后是否发生变化,如果没有变化则不生成新的数
int temp[4];
int empty;  //空格数,如果 empty = 0 那么将结束本次游戏

void init();  //初始化游戏
void show();  //将游戏画面输出
int isDifferent();  //判断输入的操作是否改变数组的值,若不改变,则不添加新的数
void op_up();  //上移操作
void op_down();  //下移操作
void op_left();  //左移操作
void op_right();  //右移操作
void addNum();  //添加新的数
void play();  //提供游戏操作输入

int main()
{
    printf("Enter any key to play game\n");
    getch();
    while (1)
    {
        system("cls");
        init();
        show();
        while (empty) play();
        printf("Game Over\n Please enter 'q' to quit, or any other keys to continue\n");
        if (getch() == 'q') exit(0);
    }
    return 0;
}

void init()
{
    for (int i = 0; i < 4; i++)
        for (int j = 0; j < 4; j++)
            copy[i][j] = arr[i][j] = 0;
    
    srand(time(0));
    int x = rand() % 4;
    int y = rand() % 4;
    copy[x][y] = arr[x][y] = 2;  //在随机位置生成数字 2 作为开局
    empty = 15;  //更新 empty
}

void show()
{
    for (int i = 0; i < 4; i++)
    {
        printf("_________________________\n");
        for (int j = 0; j < 4; j++)
        {
            if (0 == arr[i][j])
                printf("|     ");
            else
                printf("|%5d", arr[i][j]);
        }
        printf("|\n");
    }
    printf("_________________________\n");
}

int isDifferent()
{
    int flag = 0;
    for (int i = 0; i < 4; i++)
        for (int j = 0 ; j < 4; j++)
            if (arr[i][j] != copy[i][j])
            {
                flag = 1;
                goto NewCopy;
            }
    return flag;

    NewCopy:  //如果数组发生改变,则更新数组,否则不用更新
        for (int i = 0; i < 4; i++)
            for (int j = 0 ; j < 4; j++)
                if (arr[i][j] != copy[i][j])
                    copy[i][j] = arr[i][j];
        return flag;
}

void op_up()
{
    int i, j, k, t;
    for (i = 0; i < 4; i++)  //逐列处理
    {
        for (j = 0; j < 4; j++) //从头开始查找是否能合并
        {
            if  (0 == arr[j][i]) continue;  //如果是 0 则跳过,先不将0剔除,最后再去处理 0 的位置问题
            for (k = j + 1; k < 4; k++)  //k 从 j 的下一个开始与 j 对比
            {
                if (0 == arr[k][i]) continue; //跳过 0
                if (arr[j][i] == arr[k][i])
                {
                    arr[j][i] <<= 1;  //k 与 j 相等,那么合并,即等价于arr[j][i] * 2
                    arr[k][i] = 0;  //合并之后 arr[k][i] 自然为 0
                    empty++;  //更新空格数
                    k = j = 0; //合并成功,从头开始继续寻找,即 j = 0, 而 k 也要从 j + 1 开始,由于 k 还要自加,所以 k = j
                }
                else break; //合并失败,从下一个数 j + 1 开始寻找,如果一直失败则最终由 j 的循环跳出本列的处理
            }
        }
        //以下将非 0 的数上移,处理之前未处理的 0
        t = 0;
        for (j = 0; j < 4; j++)
            if (0 != arr[j][i]) temp[t++] = arr[j][i];  //将非零的 arr[j][i] 顺序复制进 temp 中
        if (t != 4)
        {
            while (t < 4) temp[t++] = 0;  //剩余的 temp 直接赋值为 0
            for (j = 0; j < 4; j++) arr[j][i] = temp[j];  //将处理好的 temp 整体复制到arr[j][i] 中
        }
    }
}

void op_down()
{
    int i, j, k, t;
    for (i = 0; i < 4; i++)
    {
        for (j = 3; j >= 0; j--)
        {
            if (0 == arr[j][i]) continue;
            for (k = j - 1; k >= 0; k--)
            {
                if (0 == arr[k][i]) continue;
                if (arr[k][i] == arr[j][i])
                {
                    arr[j][i] <<= 1;
                    arr[k][i] = 0;
                    empty++;
                    k = j = 3;
                }
                else break;
            }
        }

        t = 3;
        for (j = 3; j >= 0; j--)
            if (0 != arr[j][i]) temp[t--] = arr[j][i];
        if (t != -1)
        {
            while (t >= 0) temp[t--] = 0;
            for (j = 0; j < 4; j++) arr[j][i] = temp[j];
        }
    }
}

void op_left()
{
    int i, j, k, t;
    for (i = 0; i < 4; i++)
    {
        for (j = 0; j < 4; j++)
        {
            if (0 == arr[i][j]) continue;
            for (k = j + 1; k < 4; k++)
            {
                if (0 == arr[i][k]) continue;
                if (arr[i][k] == arr[i][j])
                {
                    arr[i][j] <<= 1;
                    arr[i][k] = 0;
                    empty++;
                    k = j = 0;
                }
                else break;
            }
        }

        t = 0;
        for (j = 0; j < 4; j++)
            if (0 != arr[i][j]) temp[t++] = arr[i][j];
        if (t != 4)
        {
            while (t < 4) temp[t++] = 0;
            for (j = 0; j < 4; j++) arr[i][j] = temp[j];
        }
    }
}

void op_right()
{
    int i, j, k, t;
    for (i = 0; i < 4; i++)
    {
        for (j = 3; j >= 0; j--)
        {
            if (0 == arr[i][j]) continue;
            for (k = j - 1; k >= 0; k--)
            {
                if (0 == arr[i][k]) continue;
                if (arr[i][k] == arr[i][j])
                {
                    arr[i][j] <<= 1;
                    arr[i][k] = 0;
                    empty++;
                    k = j = 3;
                }
            }
        }

        t = 3;
        for (j = 3; j >= 0; j--)
            if (0 != arr[i][j]) temp[t--] = arr[i][j];
        if (t != -1)
        {
            while (t >= 0) temp[t--] = 0;
            for (j = 0; j < 4; j++) arr[i][j] = temp[j];
        }
    }
}

void addNum(){
    int x, y;
    srand(time(0));
    do
    {
        x = rand() % 4;
        y = rand() % 4;
    } while (arr[x][y] != 0);  //随机取一个为空的位置生成新的数
    copy[x][y] = arr[x][y] = (rand() & 0x1? 2 : 4); //利用随机数决定生成的是 2 还是 4
    empty--;
}

void play(){
    char op = getch();
    while (op != 72 && op != 80 && op != 75 && op != 77)  //如果不是方向键,则继续输入
        op = getch();

    switch (op){
        case 72: op_up();  break;
        case 80: op_down();  break;
        case 75: op_left();  break;
        default: op_right();
    }
    if (isDifferent())
    {
        addNum();  //加入新生成的数
        system("cls");
        show();
    }
}
使用方向键控制,游戏截图如下

猜你喜欢

转载自blog.csdn.net/qq_35215641/article/details/80640792