原创

c语言实现2048游戏

温馨提示:
本文最后更新于 2019年03月12日,已超过 1,843 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

经过一天的学习研究,终于实现了c语言dos版本的2048游戏,通过wsad控制方向,esc,q键退出,空格键重新开始,实现了计分板功能,代码如下:

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>     // for rand() and srand() and exit()
#include <windows.h>    // for system()
#include <string.h>     //字符串操作函数
#include <sys/time.h>   //系统时间

void welcome(void);//欢迎界面
void cls(void);//清屏
void init(void);//初始化元素
void draw(void);//绘制图形
int mt_rand(int, int);//随机数专用
void play(void);//游戏中
void addNumber(void);//新增数字
void keyUp(void);//向上事件;
void keyDown(void);//向下事件;
void keyLeft(void);//向左事件;
void keyRight(void);//向右事件;
void gameOver(int);//结束事件;
void isGameOver(void);//判断游戏是否结束;
int map[4][4];
int emptyNum = 16;//地图元素为空数量
int scores = 0;

void main(void) {
    srand(time(0));//随机数播种
    welcome();
    init();
    cls();
    draw();
    while (1) {
//        printf("%d\n",getch());
        isGameOver();
        play();
        Sleep(100);
    }
}

/**
 * 欢迎界面
 */
void welcome(void) {
    printf("****************************\n");
    printf("          2048 doc版        \n");
    printf("       通过w/s/a/d控制      \n");
    printf("   通过字母q或esc退出游戏   \n");
    printf("    通过空格键可重新开始    \n");
    printf("     请按任意键开始游戏     \n");
    printf("****************************\n");
    getch();//阻塞方式等待按键
}

/**
 * 初始化界面元素
 */
void init(void) {
    int x, y;
    emptyNum = 16;
    scores=0;
    for (x = 0; x < 4; ++x) {
        for (y = 0; y < 4; ++y) {
            map[x][y] = 0;
        }
    }
    x = mt_rand(1, 4) % 4;
    y = mt_rand(1, 4) % 4;
//    x = 1;
//    y = 3;
    map[x][y] = 2;
    emptyNum--;//为空数量减一
}

/**
 * 运行游戏
 */
void play(void) {
    //检测em

    //监听按键
    int key = getch();
    switch (key) {
        case 119:    // 向上移动
        case 87:
            keyUp();
            cls();
            addNumber();
            draw();
            break;
        case 115:    // 向下移动
        case 83:
            keyDown();
            cls();
            addNumber();
            draw();
            break;
        case 97:    // 向左移动
        case 65:
            keyLeft();
            cls();
            addNumber();
            draw();
            break;
        case 100:     // 向右移动
        case 68:
            keyRight();
            cls();
            addNumber();
            draw();
            break;
        case 27:   // 退出游戏
        case 113:
        case 81:
            cls();
            printf("****************************\n");
            printf("           确定退出?        \n");
            printf("     Enter确定,其他键取消   \n");
            printf("****************************\n");
            int key = getch();
            if (key == 13) {
                gameOver(1);
            } else {
                cls();
                draw();
            }
            break;
        case 32:
            cls();
            printf("****************************\n");
            printf("         确定重新开始?      \n");
            printf("     Enter确定,其他键取消   \n");
            printf("****************************\n");
            key = getch();
            cls();
            if (key == 13) {
                init();
            }
            draw();
            break;
        default:
            cls();
            draw();
            printf("按键错误,请重新输入\n");
            break;
    }
}

/**
 * 随机增加2,4字母
 */
void addNumber(void) {
    int temp, number;
    int x, y;
    if (emptyNum > 0) {     // 找出空格
        do {
            x = mt_rand(1, 4) % 4;
            y = mt_rand(1, 4) % 4;
        } while (map[x][y] != 0);
        number = mt_rand(1, 2);
        temp = number % 2;
        if (temp == 1) {  // 判断是生成数字2,还是数字4
            map[x][y] = 2;
            emptyNum--;
        }
        if (temp == 0) {
            map[x][y] = 4;
            emptyNum--;
        }
    }
}

/**
 * 判断游戏是否结束
 */
void isGameOver(void) {
    if (emptyNum == 0) {
        for (int x = 0; x < 4; ++x) {
            for (int y = 0; y < 4; ++y) {
                //判断右边和下边的是否相等
                if (map[x][y] != map[x + 1][y] && map[x][y] != map[x][y + 1]) {
                    gameOver(2);
                }
            }
        }
    }
}

/**
 * 游戏结束处理
 * @param overType
 */
void gameOver(int overType) {
    switch (overType) {
        case 1:
            cls();
            //正常结束
            printf("****************************\n");
            printf("           已退出...        \n");
            printf("****************************\n");
            Sleep(1);
            exit(0);
        case 2:
            cls();
            init();
            printf("****************************\n");
            printf("       游戏结束,分数:%d     \n",scores);
            printf("       是否重新开始游戏?    \n");
            printf("     Enter继续游戏,Esc退出  \n");
            printf("****************************\n");
            int key = getch();
            cls();
            switch (key) {
                case 27:
                    gameOver(1);
                    break;
                case 13:
                    welcome();
                    break;
            }
    }
}

void keyUp(void) {
    int x, y, i;
    //先合并相同的方块
    //通过y轴,上下合并
    for (y = 0; y < 4; y++) {
        for (x = 0; x < 4; ++x) {
            if (map[x][y] != 0) {
                for (i = y + 1; i < 4; ++i) {
                    if (map[x][y] == map[x][i]) {
                        map[x][y] = map[x][y] * 2;
                        scores+=map[x][y];
                        map[x][i] = 0;
                        emptyNum++;
                        break;
                    } else if (map[x][i] != 0) {
                        break;
                    } else {
                        continue;
                    }
                }
            }
        }
    }

    //向上移动数字
    for (y = 0; y < 4; y++) {
        for (x = 0; x < 4; x++) {
            if (map[x][y] == 0) {
                for (i = y + 1; i < 4; ++i) {
                    if (map[x][i] != 0) {
                        map[x][y] = map[x][i];
                        map[x][i] = 0;
                        break;
                    }
                }
            }
        }
    }
}

void keyDown(void) {
    int x, y, i;
    //先合并相同的方块
    //通过y轴,上下合并
    for (y = 3; y >= 0; y--) {
        for (x = 0; x < 4; ++x) {
            if (map[x][y] != 0) {
                for (i = y - 1; i >= 0; i--) {
                    if (map[x][y] == map[x][i]) {
                        map[x][y] += map[x][i];
                        scores+=map[x][y];
                        map[x][i] = 0;
                        emptyNum++;
                        break;
                    } else if (map[x][i] != 0) {
                        break;
                    } else {
                        continue;
                    }
                }
            }
        }
    }

    //向下移动数字
    for (y = 3; y >= 0; y--) {
        for (x = 0; x < 4; x++) {
            if (map[x][y] == 0) {
                for (i = y - 1; i >= 0; i--) {
                    if (map[x][i] != 0) {
                        map[x][y] = map[x][i];
                        map[x][i] = 0;
                        break;
                    }
                }
            }
        }
    }
}

void keyLeft(void) {
    int x, y, i;
    //先合并相同的方块
    //通过x轴,左右合并
    for (x = 0; x < 4; x++) {
        for (y = 0; y < 4; ++y) {
            if (map[x][y] != 0) {
                for (i = x + 1; i < 4; ++i) {
                    if (map[x][y] == map[i][y]) {
                        map[x][y] = map[x][y] * 2;
                        scores+=map[x][y];
                        map[i][y] = 0;
                        emptyNum++;
                        break;
                    } else if (map[i][y] != 0) {
                        break;
                    } else {
                        continue;
                    }
                }
            }
        }
    }

    //向左移动数字
    for (x = 0; x < 4; x++) {
        for (y = 0; y < 4; y++) {
            if (map[x][y] == 0) {
                for (i = x + 1; i < 4; ++i) {
                    if (map[i][y] != 0) {
                        map[x][y] = map[i][y];
                        map[i][y] = 0;
                        break;
                    }
                }
            }
        }
    }
}

void keyRight(void) {
    int x, y, i;
    //先合并相同的方块
    //通过x轴,左右合并
    for (x = 3; x >= 0; x--) {
        for (y = 0; y < 4; ++y) {
            if (map[x][y] != 0) {
                for (i = x - 1; i >= 0; i--) {
                    if (map[x][y] == map[i][y]) {
                        map[x][y] += map[i][y];
                        scores+=map[x][y];
                        map[i][y] = 0;
                        emptyNum++;
                        break;
                    } else if (map[i][y] != 0) {
                        break;
                    } else {
                        continue;
                    }
                }
            }
        }
    }

    //向右移动数字
    for (x = 3; x >= 0; x--) {
        for (y = 0; y < 4; y++) {
            if (map[x][y] == 0) {
                for (i = x - 1; i >= 0; i--) {
                    if (map[i][y] != 0) {
                        map[x][y] = map[i][y];
                        map[i][y] = 0;
                        break;
                    }
                }
            }
        }
    }
}

/**
 * 绘制游戏界面
 */
void draw(void) {
    int x, y;
    //绘制第一行横线
    printf(" ___________________");
    printf("\n");
    for (y = 0; y < 4; ++y) {          // 一个方格由三根竖线组成
        for (x = 0; x < 4; ++x) {     // 第一排竖线 每个竖线之间占5个格
            printf("|    ");
        }
        printf("|\n");
        for (x = 0; x < 4; ++x) {   // 第二排竖线与数字
            if (map[x][y] == 0) {
                printf("|    ");
            } else {
                printf("|%4d", map[x][y]);
            }
        }
        printf("|\n");

        for (x = 0; x < 4; ++x) {    // 第三排竖线加底线
            printf("|____");
        }
        printf("|\n");
    }
    //输出分数
    printf("分数:%d \n", scores);
}

/**
 * 清屏
 */
void cls(void) {
    system("cls");
}

/**
 * 根据区间随机
 * @param start
 * @param end
 * @return
 */
int mt_rand(int start, int end) {
    return rand() % (end + 1 - start) + start; /*生成一个[start,end)区间内的整数*/
}

游戏截图如下:

正文到此结束
本文目录