2021-11-10-
作者:Nico
时间: 2021-11-10
网站地址:[]:https://github.com/sxfinn
摘要
C语言实现我们小时候玩过的扫雷游戏,最近看到了一些扫雷游戏的简单实现,但是总有功能上的缺失,玩起来不那么的“原汁原味”,因此我增加了一些新功能:
- 确保玩家首次排雷一定不会炸死。
- 加入了计时器记录结束时间。
- 扩展式排雷,展开周围的非雷区。
总结
比较难的一点是扩展式排雷,使用用递归函数处理相对方便。
难点解析
探索八区
探索排雷位的周围八个区域。
总归情况就分三类,可探索的区域为8个,5个,3个。但这样分类实在麻烦,所以我们可以选择在创建雷盘的时候,将二维数组的维度扩大一些,使其不用考虑多种情况,而只用考虑探索周围八个雷区。
我们可以给外侧再加一层,即给二维数组行列分别加二,并且把外层全部设置为非雷区域,就可以解决这一问题。
递归展开
展开周围的非雷区
递归过程:如果(x,y)位置周围八区的雷数为0,则从八个区域展开,展开的位置的 x坐标是从x-1到x+1,而 y 的位置是从y-1到y+1的范围中,因此嵌套两重循环。
进入条件:只有之前没有展开过,且坐标在雷盘内的位置才进入递归。
终止条件:如果探索的周围八个位置有雷,则停止,并让该位置显示雷的数量。
探索八区代码实现:
提醒:’*‘是未排雷的区域,’ ‘是代表已经展开过的区域。
//计算排查位置处周围雷的个数
int calculate(char mine[ROWS][COLS],int x,int y)
{
//因为雷的位置放的是字符‘1’
// 加起来之后应该分别减去‘0’,才得到雷的个数
return
mine[x - 1][y - 1] +
mine[x - 1][y] +
mine[x - 1][y + 1] +
mine[x][y - 1] +
mine[x][y + 1] +
mine[x + 1][y - 1] +
mine[x + 1][y] +
mine[x + 1][y + 1] - 8 * '0';
}
//展开周围都没有雷的雷盘(扩展式排雷)
void expand(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)//扩展函数
{
//利用calculate函数判断周围是否有雷
if (calculate(mine, x, y) == 0)
{
//判断周围雷的个数,若为0,则需要展开
show[x][y] = ' ';//展开的位置都置为空格
int i = 0;
int j = 0;
//该位置可以拓展才检查周围8个位置是否能拓展
for (i = x - 1; i <= x + 1; i++)
{
for (j = y - 1; j <= y + 1; j++)
{
if (show[i][j] == '*' && i > 0 && i <= ROW && j > 0 && j <= COL)
{
//如果该位置未被扫过且在棋盘范围内则继续递归调用expand函数
//再依次进入判断周围8个位置是能被展开还是不能
expand(mine, show, i, j);
}
}
}
}
else
{
show[x][y] = calculate(mine, x, y)+'0';
//不需要展开则显示附近雷的个数
}
}
这两个函数结合起来使用便可以达到扩展展开的效果。
使用效果:
可以看到在选择(5,6)后一片非雷区被展开了,并且边缘部分的雷个数被打印在了相应位置。
由于实在找不到什么好看的符号代替’ ‘,看着可能会有点难受😭,欢迎评论区给出建议!
完整源码
我将代码分为了test.c
、game.h
、game.c
三个部分。
test.c
是游戏实现的主体框架。
game.h
是所用到的头文件以及自定义函数声明。
game.c
是游戏的具体实现模块。
除了上面的递归有些难度外,其他的都比较易懂,不再单独阐述,下面的源码中我给出了每一步的注释,解释的很清楚,相信各位一边看代码一边想会有更多的收获。
test.c
#