c语言期中项目实战二—扫雷递归版,思路分析+代码注释
Posted 小海浪.
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c语言期中项目实战二—扫雷递归版,思路分析+代码注释相关的知识,希望对你有一定的参考价值。
基本思路讲解
扫雷普通版,及更加详细讲解可以看一下我之前写的一篇扫雷文章,这里就不在过多赘述了,看完普通的版本再来看一下递归的版本会更好一些(大神随意)。
普通版扫雷连接
这篇博文实现的是递归扫雷,也就是扫雷时如果所排坐标周围八个坐标都没雷的话,把它的位置设置为空格(空白),再递归的去看这个坐标周围的周围的坐标是不是也是八个位置都没有雷,如此递归下去,直到递归下去的坐标没有一个周围八个坐标都没有雷为止。(周围八个坐标都没有雷的坐标递归的时候要首先把坐标设置为‘ ’,及空白)这样增加扫雷的速度及游戏体验,大致效果如下图:
函数递归展开
什么是递归
程序调用自身的编程技巧称为递归( recursion)。 递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。 递归的主要思考方式在于:把大事化小
递归的两个必要条件
- 存在限制条件,当满足这个限制条件的时候,递归便不再继续
- 每次递归调用之后越来越接近这个限制条件
代码实现
递归代码实现
void SetBlank(char show[ROWS][COLS], char mine[ROWS][COLS], int x, int y)
{
int count = get_mine_count(mine, x, y);
if (count == 0)
{
show[x][y] = ' ';//避免重复递归
if (x - 1 >= 0 && x <= ROW && y >= 0 && y <= COL && show[x - 1][y] == '*')
SetBlank(show, mine, x - 1, y);
if (x + 1 >= 0 && x + 1 <= ROW && y >= 0 && y <= COL && show[x + 1][y] == '*')
SetBlank(show, mine, x + 1, y);
if (x >= 0 && x <= ROW && y - 1 >= 0 && y - 1 <= COL && show[x][y - 1] == '*')
SetBlank(show, mine, x, y - 1);
if (x >= 0 && x <= ROW && y + 1 >= 0 && y + 1 <= COL && show[x][y + 1] == '*')
SetBlank(show, mine, x, y + 1);
}
else
{
show[x][y] = count + '0';//存放的数字字符
}
}
代码解释
在这里的限制条件就是,找出所有周围雷个数为0的位置,找完后递归结束。
为了避免重复检查,每找到一个位置,都把原来的符号替换成‘ ’(空白),初始化显示棋盘的符号为’ * ',则进行替换。下次递归时先检查其位置的符号是否为 ’ * '。x,y是玩家输入的坐标,先用坐标计算其周围雷的个数,若为0,把该位置符号’ * ‘替换成空格 ‘ ’,之后递归其上下左右四个方向的坐标。首先计算当count=0,判断坐标的合法性,然后检查该位置符号是否’ * ',避免重复递归,那么接着递归它们上下左右的坐标,进入SetBlank函数,重复前面的流程,就会检查该位置上下左右的坐标,然后上下左右的坐标又会各自检查它们上下左右的坐标,并一直更新周围位置的count数,如此反复,直到不再出现count=0的情况为止。
判断输赢函数
统计最终显示在棋盘中的’ * '的个数,如果和布雷数一致,那么说明排雷成功,退出找雷。
int CountMine(char show[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
int count = 0;
for (i = 1; i <= row; i++)
{
for (j = 1; j <= col; j++)
{
if (show[i][j] == '*')
count++;
}
}
return count;
}
排雷函数
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
while (1)
{
int x = 0;
int y = 0;
printf("请输入要排查的坐标,中间用空格隔开:>\\n");
scanf("%d%d", &x, &y);//x--(1,16) y--(1,16)
//判断坐标的合法性
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死了!!!\\n");
DisplayBoard(mine, row, col);//打印一下你排的位置是雷,你是怎么死的
break;//跳出循环,继续游戏
}
else
{
//2.该坐标处是不是雷?不是雷,统计周围雷的个数
//3.扩展空白
SetBlank(show, mine, x, y);
int count = CountMine(show, row, col);
if (count == EASY_COUNT)
{
printf("恭喜你,排雷成功!\\n");
DisplayBoard(show, row, col);
break;
}
DisplayBoard(show, row, col);
}
}
else
{
printf("坐标不合法,请重新输入\\n");
}
}
}
组合代码实现功能
该递归版本和普通版本差不多思路。只是加了递归函数SetBlank和判断输赢函数CountMine。之后排雷函数那不同改了一下,再在game.h文件里面声明那个递归函数即可实现功能。
总结
我写的普通扫雷和递归都很简单,还没实现更复杂的功能,如标记雷,保证第一次踩到的不是雷,扫雷记时,美化等。代码需要改进,鉴于技术及时间的限制目前就这样吧!之后有时间有能力再写一些复杂的功能,完善的代码和大家分享。如文章哪里有问题或者有疑问欢迎评论区留言哦。
哈哈,大家如果觉得写的不错,别忘了给个三连鼓励一下作者,欢迎相互关注,相互交流~(五一爆头,非爆肝啊)。
以上是关于c语言期中项目实战二—扫雷递归版,思路分析+代码注释的主要内容,如果未能解决你的问题,请参考以下文章