如何用C语言实现扫雷游戏
一.前言
1.什么是扫雷游戏
如图所示是一个网页版的在线扫雷游戏 扫雷游戏在线链接 相信大家应该都听说过扫雷这个游戏,或者在微机课上偷偷摸鱼的时候玩过这个游戏,也有没玩过的人以为这就是靠运气玩的,实际上它的游戏规则是:随机点开一个格子,如果显示一个数字,就代表以它为中心的九宫格有多少个雷,根据数字推断出哪个格子是雷,并点击鼠标右键用小旗帜做出标记,当你把所有的雷都排查出来以后代表游戏胜利。当然了如果你运气不好,上来第一个就开到了雷那你就直接失败了哈哈哈。大家可以点击蓝色链接先玩一下~
二.扫雷游戏设计
1.扫雷游戏菜单简介
上图所示是一个16*16的棋盘,在游戏顶部可以选择“基础”、“中级”、“专家”、“满屏”、“自定义”五种难度模式,不同模式对应雷的个数也不相同。
游戏界面左上角的数字代表总的雷的个数减去你做的标记的个数(并不代表剩下的雷的个数),右上角代表从游戏开始到目前所使用的时间。
2.扫雷游戏功能简介
扫雷游戏功能的底层逻辑是:有两个棋盘一个棋盘用来布置雷,另一个用来排查雷。在第一个棋盘随机布置好雷后,在另一个棋盘排查雷,如果点击后是雷则游戏失败,如果不是雷,则显示以该位置为九宫格中心附近有几个雷。当把所有雷的位置都标记出来以后游戏胜利。
因此当我们自己设计代码模拟实现扫雷游戏时,应该具有上述大概游戏界面和功能。
三.扫雷游戏模拟实现
1.扫雷游戏需具备的基础功能
1.在调试控制台窗口实现扫雷游戏的界面和完成
2.能够实现雷的随机布置
3.能够实现雷的排查:
①如果不是雷,则显示九宫格内有几个雷。
②如果是雷则被炸死,游戏结束。
③排查出来所有雷之后游戏胜利。
4.游戏玩完后可以选择退出或者继续
2.扫雷游戏菜单的实现
1.在编译软件里创建一个新项目来存放所写的代码,例如:
2.因为扫雷游戏涉及多个功能的实现,可以将它封装成多个代码来进行实现。
例如:test.c----main函数,实现游戏的主逻辑,game.h—游戏的声明,game.c—游戏的实现
3.因为在玩完一局之后,可以在菜单上选择是否继续玩或者退出,所以可以使用do while循环实现函数,并且可以将菜单写成函数的形式,避免主体函数过大。
void menu()
{
printf("1. play game\n");
printf("0. exit game\n");
}
int main()
{
int input = 0;
do {
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
printf("开始扫雷");
game();
break;
case 0:
printf("结束游戏");
break;
default:
printf("选择错误,请重新选择:");
break;
}
}while (input);
return 0;
}
3.扫雷游戏功能的实现
1.数组的创建:
我们需要创建两个数组,一个数组用来随机布置雷,另一个用来在屏幕上显示,供我们排查雷。假如现在要设计一个9×9的棋盘格,可以使用二维数组来实现打印棋盘格,为了避免边界的位置不好统计雷的个数,可以将棋盘扩大一圈,实际上设计一个11×11的棋盘格,如图所示:
其中一个棋盘用来布置随机雷的位置,另一个用来显示在屏幕上,供我们进行扫雷游戏的完成。在布置雷的棋盘上,我们可以用字符 ‘ 1 ’表示雷,字符 ‘ 0 ’表示非雷,在另外一个显示的棋盘上将所有位置都初始化为“ * ”,因此可以用char类型的二维数组
2.初始化棋盘:
我们可以自定义一个函数为InitBoard来初始化我们的数组,并且将这个函数的定义放到game.c文件中,方便后续使用。同时为了使扫雷游戏的棋盘的大小可以自己设 置,我们使用宏定义来实现行数和列数的设置。
//InitBoard函数的定义
void InitBoard(char board[ROWS][COLS], int row, int col, char set)
//char board[][]为形参二维数组,row为行数,col为列数,set为二维数组要初始化的值
{
int i = 0;//行下标
int j = 0;//列下标
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = set;
}
}
}
宏定义为:
//使用宏定义行数和列数,方便修改
#define ROW 9
#define COL 9
//设置棋盘大小时实际上都要扩大一圈
#define ROWS ROW+2
#define COLS COL+2
3.打印棋盘:
我们可以写一个DisplayBoard函数来完成对棋盘的打印,需要注意的是假如我们要玩9×9大小的扫雷,我们在初始化数组时是将数组扩大一圈变成11×11来初始化,但打印的时候还是将中间9×9的内容打印下来。
//DisplayBoard函数的定义(打印棋盘)
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;//行下标
int j = 0;//列下标
for (i = 1; i <= row; i++)
{
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");//每次打印完一行后就换行
}
}
到目前代码运行的结果应该如图
为了能更清楚的看出某个位置是第几行第几列,我们可以在打印数组函数上做出一点小小的优化。
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;//行下标
int j = 0;//列下标
for (i = 0; i <= row; i++)
{
printf("%d ", i); //打印列标
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i); //打印行标
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");//每次打印完一行后就换行
}
printf("\n");
}
4.随机布置雷:
要想实现雷的随机布置,就要实现雷的下标的随机生成,行下标和列下标的范围应该都是1~9之间,因此我们可以用rand()%row+1来获得1到9之间的数字。同时要注意布置雷的位置不能重复,因此在布置雷之前应该先检测这个位置是否被布置过雷。假如我们在9×9的格子上布置10个雷,我们就可以使用while循环,每次布置完一个雷之后使用自减.
//SetMine函数的定义(随机布置雷)
void SetMine(char board[ROWS][COLS],int row,int col)
{
int Mine = 10;
int x = 0;
int y = 0;
while (Mine--)
{
x = rand() % row + 1;
y = rand() % col + 1;
if (board[x][y] != '1')
board[x][y] = '1';
}
}
5.排查雷:
可以通过输入坐标来排查某个位置是否是雷来完成排查雷函数的实现,需要注意的是首先这个坐标应该是在棋盘格范围之内的,其次可以在写一个函数来实现对某个位置周围八个格子内雷的个数的排查。并且用while循环在排查出所有非雷位置后结束游戏。
//FindMine函数的定义(排查雷)
void FindMine(char board1[ROWS][COLS], char board2[ROWS][COLS], int row, int col)
{
int x = 0; //要排查位置的行下标
int y = 0; //要排查位置的列下标
int count = row*col-10;//用于统计剩余雷的个数
while (count)
{
printf("请输入要排查的坐标:");
scanf("%d%d", &x, &y);
if (x < 1 || x>9 || y < 1 || y>9)
printf("输入错误,请重新输入\n");
else
{
if (board1[x][y] == '1')
{
printf("扫到了雷,游戏失败");
break;
}
else
{
//排查周围雷的函数
int ret=MineCount(board1,x,y);
board2[x][y] = ret+'0';
DisplayBoard(board2, ROW, COL);
}
count--;
}
}
if (count == 0)
printf("恭喜你,扫雷成功,游戏胜利!");
DisplayBoard(board1, ROW, COL);
}
对某个位置周围八个格子内雷的个数的排查,可以通过for循环,来对九宫格的每个位置进行排查。
//排查某个位置周围雷的个数
int MineCount(char board1[ROWS][COLS], int x, int y)
{
int count = 0;
int a = 0;
int b = 0;
for (a=x-1; a < x + 2; a++)
{
for (b=y-1; b < y + 2; b++)
{
if (board1[a][b] == '1')
count++;
}
}
return count;
}
6.以上就是扫雷游戏所需的大致功能了,大家可以现在运行试玩一下。
四.总结
1.目前的不足
当前我们完成了一个简易的扫雷小游戏的设计,但实际在玩的过程中我们会发现还有许多不足。例如,必须要将所有不是雷的位置一一排除、雷的个数不方便修改以及某些位置多次被排查等问题,我们可以在以后练习更多代码以后对当前的代码进行优化修改
2.个人总结
这篇博客是我在第二次练习扫雷游戏的时候写了好几天终于写出来的,码字不易,希望大家多多支持,有哪里不足的地方也希望大家能私信告诉我哦~