前言
本篇文章要实现的是扫雷游戏,其代码实现与上一篇的三子棋游戏类同,都是在棋盘的基础上,与电脑进行对抗,不同的是,扫雷游戏一开始电脑就已经随机布置好了所有“雷”。
1. 扫雷游戏玩法
经典玩法:
扫雷就是要把所有非地雷的格子揭开即胜利;踩到地雷格子就算失败。
游戏主区域由很多个方格组成。选择一个方格,方格即被打开并显示出方格中的数字,
而方格中数字则表示其周围的8个方格隐藏了几颗雷;如果点开的格子为空白格,即其周围有0颗雷,则其周围格子会自动打开。
本机玩法:
游戏开始,玩家在棋盘格上输入正确的行列坐标选择位置,若选择到的是非地雷,就会显示出周围8个格子存在雷的数量,直到把所有非雷的格子都选出来,游戏胜利;若“踩雷”了,则游戏失败。
看似简单的扫雷游戏,想要胜利,走的每一步都需要推算
2. 设计思路
游戏都需要一个开关去控制它,所以一个菜单界面是必不可少的,通过菜单去选择play还是exit。
而对于游戏的实现:
1.首先需要创建一个n*n的棋盘格,可以用二维数组实现,自定义它的大小
2.在玩家选择位置前,就要布置好雷的数量,随机埋下雷的位置,并用一个二维数组来存放布置好的雷
3.玩家通过提示,输入正确的坐标选择位置,如果选择的是非雷坐标,就显示出周围雷的数量,用一个二维数组来存放排查出的雷的信息(数量)
坐标选择后的状态有两种:
- 选择的坐标是非雷的,显示周围雷的数量,一直到排查完所有的雷,即所有的坐标都选择完了且没有踩雷,游戏胜利
- 选择的坐标是有雷的,游戏失败
2.1 准备工作
🍥 建立 test.c 源文件 – 测试游戏代码
🍥 建立 game.c 源文件 – 游戏的实现
🍥 建立 game.h 头文件 – 游戏函数声明
2.2 主函数设计
为了控制游戏的进行,我们设置一个菜单选项,选1时玩游戏,选择0,则退出游戏。
🍤 代码实现:
//test.c int main() { //菜单 printf("----1. play----\n"); printf("----0. exit----\n"); //进行选择 int input; printf("请选择:"); scanf("%d", &input); switch (input) { case 1: game();//游戏函数 break; case 0: printf("退出游戏\n"); break; default: printf("选择错误,请重新选择\n"); break; } return 0; }
当玩家想要一直玩游戏,该怎么办呢? 加入循环
同时,为了使主函数简洁明了,我们将菜单放在主函数外面,使用menu函数来实现
//test.c void menu() { printf("----1. play----\n"); printf("----0. exit----\n"); } int main() { int input; srand((unsigned int)time(NULL));//设置随机种子 do { menu(); printf("请选择:"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出游戏\n"); break; default: printf("选择错误,请重新选择\n"); break; } system("cls"); Sleep(100); } while (input); return 0; }
🍤 菜单显示:
2.3 设计棋盘
想打印一个9x9的棋盘格实现游戏,我们就需要先创建两个二维数组(11x11),一个存放布置好的雷,一个存放排查出的雷的信息。
为什么是11x11?
考虑到棋盘边缘的位置,周围并不能的格子不能都满足8个,所以为了防止在统计坐标周围的雷的个数的时候越界,所以让数组设计为11x11,这里的11x11并不会全部打印出来
char mine[ROWS][COLS];//存放布置好的雷 char show[ROWS][COLS];//存放排查出的雷的信息
仔细观察就会发现,这里的数组大小为什么是ROWSxCOLS***,而不是11x11*呢?
在下面设计棋盘时,我们的大小与这里是相同的,而为了后期可以方便的调整大小,我们就在game.h文件中就定义这两个全局变量的大小
🍤 代码实现:
#define ROW 9//显示的棋盘大小 #define COL 9 #define ROWS ROW+2//棋盘真正大小 #define COLS COL+2
2.3.1 初始化棋盘
//game.c void InitBoard(char board[ROWS][COLS],int rows, int cols,char set) { int i = 0; for (i = 0; i < rows; i++) { int j = 0; for (j = 0; j < cols; j++) { board[i][j] = set; } } }
🍤 调用:
//test.c void game() { char mine[ROWS][COLS];//存放布置好的雷 char show[ROWS][COLS];//存放排查出的雷的信息 //初始化棋盘 //1.mine数组最开始全‘0’、 //2.show数组最开始全‘*’ InitBoard(mine,ROWS,COLS,'0'); InitBoard(show,ROWS,COLS,'*'); }
2.3.2 打印棋盘
用DisplayBoard函数实现棋盘打印,为了玩家有更好的游戏体验,我们在棋盘格的最顶端和最左边提示坐标信息,方便玩家快速的锁定行列数。
//game.c void DisplayBoard(char board[ROWS][COLS], int row, int col) { int i = 0; printf("------扫雷^-^------\n");//文字提示 for (i = 0; i <= col; i++) { printf("%d ", i);//顶端打印列数 } printf("\n");//换行打印棋盘 for (i = 1; i <= row; i++) { printf("%d ", i);//最左边打印行数 int j = 0; for (j = 1; j <= col; j++) { printf("%c ", board[i][j]); } printf("\n"); } }
打印棋盘时,只用打印出9x9大小的棋盘格
//打印棋盘 DisplayBoard(show, ROW, COL);//打印棋盘函数调用
🍤运行结果: