前言
本篇文章要实现的是扫雷游戏,其代码实现与上一篇的三子棋游戏类同,都是在棋盘的基础上,与电脑进行对抗,不同的是,扫雷游戏一开始电脑就已经随机布置好了所有“雷”。
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);//打印棋盘函数调用
🍤运行结果:
