当前位置: 首页 > news >正文

扫雷游戏(优化)

上篇所写的扫雷游戏即一个个位置猜,展开看周围有几个雷,但其实是有一种特殊情况是可以优化的,就是周围0的个数是0,那么我们是不是就可以无风险的把周围8个雷全部自动展开,若是展开的数中也有周围雷的个数为0的,那么就将他周围的数也全部展开,这样类似于嵌套的结构可以使用函数递归。简化了无效扫雷的过程,优化结构

如图可以达到展开一片的效果

刚开始我的想法是创建一个judgement函数,内容就是如果周围的雷的和为0,那么就将周围的数全部展开,同时若展开的数里面有和为0的,就将这个数套用到这个函数里,初次写出来是这样的

void judgement(char mine[ROWS][COLS], char show[ROWS][COLS],int count, int x, int y) { if (count == 0) { int i = 0; for (i = -1; i <= 1; i++) { int j = 0; for (j = -1; j <= 1; j++) { int count = GetMineCount(mine, x + i, y + j); show[x + i][y + j] = count + '0'; judgement(mine, show, count, x + i, y + j); } } } show[x][y] = count + '0';

可是陷入了死循环,这里犯了三个易错的问题

1.i和j都为0时,函数递归就死循环了,重新回到原来的情况

2.有超出边界的风险,必须给x+i和y+j设置边界

3.即使排除了i和j都为0的情况,也可能出现重复展开导致死循环,故必须设置一个要求,展开过的数不能再次进行展开

改正后的代码如下

void judgement(char mine[ROWS][COLS], char show[ROWS][COLS],int count, int x, int y) { if (count == 0) { int i = 0; for (i = -1; i <= 1; i++) { int j = 0; for (j = -1; j <= 1; j++) { if (show[x + i][y + j] != '*') { continue; //已经被递归过的坐标就不用递归了 要不然你把x -1 y位置递归后 递归这个坐标的时候就会重新递归到x y死循环 } if (i == 0 && j ==0) { continue; } if (x + i < 1 || y + j < 1 || x + i > 9 || y + j > 9) { continue; } int count = GetMineCount(mine, x + i, y + j); show[x + i][y + j] = count + '0'; judgement(mine, show, count, x + i, y + j); } } } show[x][y] = count + '0';

但是优化了扫雷的部分,那么此前判断扫雷是否成功的程序就需要调整了

while (win<col*row-EASY_COUNT) { printf("请输入要排查的坐标:"); scanf("%d %d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col) { //输入的位置是雷 if (mine[x][y] == '1') { printf("很遗憾,你踩雷了,游戏结束\n"); DisplayBoard(mine, ROW, COL); break; } else //不是雷 { int count = GetMineCount(mine, x, y); show[x][y] = count + '0'; DisplayBoard(show, ROW, COL); win++; } } else { printf("输入的坐标有误x(1~9),y(1~9),重新输入"); } } if (win == row * col - EASY_COUNT) { printf("恭喜你,排雷成功\n"); DisplayBoard(mine, ROW, COL); } }

这个win就需要改了,应为不再是猜一次排出一个位置,有时候展开一片的时候,一次排了很多位置,所以就不能用猜的次数来判断是否扫雷成功,可以用统计*的数量来判断(show里面的*表示还没有判断过),每次扫雷之后就进行判断,如果*的数量为10了就说明扫雷成功了。

int win = 0; for (int i = 1; i <= ROW; i++) { for (int j = 1; j <= COL; j++) { if (show[i][j] == '*') { win++; } } } if (win == 10) { printf("恭喜你,排雷成功\n"); DisplayBoard(mine, ROW, COL); break; }

int win=0不能放在其他位置,因为每次判断后如果win不等于10那么他的值是要清零的,不可以影响到下一次扫雷时win的判断

然后while是否继续循环的条件也不能用之前那个,可以改成死循环,win满足条件(win==10)退出循环即可

while (1) { printf("请输入要排查的坐标:"); scanf("%d %d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col) { //输入的位置是雷 if (mine[x][y] == '1') { printf("很遗憾,你踩雷了,游戏结束\n"); DisplayBoard(mine, ROW, COL); break; } else //不是雷 { int count = GetMineCount(mine, x, y); judgement(mine, show, count, x, y); int win = 0; for (int i = 1; i <= ROW; i++) { for (int j = 1; j <= COL; j++) { if (show[i][j] == '*') { win++; } } } if (win == 10) { printf("恭喜你,排雷成功\n"); DisplayBoard(mine, ROW, COL); break; } } DisplayBoard(show, ROW, COL); } else { printf("输入的坐标有误x(1~9),y(1~9),重新输入"); } }

其他地方与此前的扫雷程序没有区别,仅仅是对细节进行一些优化

http://www.jsqmd.com/news/608786/

相关文章:

  • 避坑指南:ESP32C3开发板音频系统常见问题排查(I2S+ES8311实战)
  • AI新手必读:从零开始,彻底搞懂AIGC与大模型(收藏版)
  • 别再死记硬背SAC公式了!用CleanRL代码逐行拆解,手把手教你理解熵正则化与重参数化
  • 抖音无水印下载神器:三分钟掌握批量下载技巧
  • 项目实训——大数据租房推荐智能体(爬虫部分1)
  • 20251906 2025-2026-2 《网络攻防实践》第三周作业
  • 第十五届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组个人题解
  • 【Linux复习】:进程信号
  • Qwen2-VL-2B多模态向量模型教程:图文嵌入向量用于多标签图像分类迁移学习
  • RFID智能柜-RFID智能柜厂家推荐 - 聚澜智能
  • Dell R720服务器安装Ubuntu避坑指南:从BIOS设置到分区优化全流程
  • Nginx本地缓存API
  • 程序控制结构
  • Altium AD20差分对走线实战:如何用交互式布线快速搞定高速信号线
  • ABAQUS用户子程序进阶指南——UMAT参数详解与实战配置
  • 通俗秒懂:储能控制器在电网调频中的关键作用与实现原理
  • 软件需求工程教案
  • Golang如何设置HTTP路由_Golang HTTP路由教程【实用】
  • 一张图看懂巴菲特 48 年投资帝国:知识图谱效果全展示
  • 别再手动配环境了!用ModelScope官方镜像5分钟搞定AI模型运行环境(附最新CPU/GPU镜像地址)
  • 【转载】ROS 中 CMakeLists.txt 文件使用的讲解与总结
  • Workstation 避坑指南:网络总连不上?深度解析常见网络配置故障与底层排错逻辑
  • 【计算机网络八股】【欧弟求职】TCP相关
  • 一台服务器跑4个独立站,我是怎么做到的?
  • 魔兽争霸III终极优化指南:免费解决老游戏在现代电脑的兼容性问题
  • RFID智能柜-RFID智能柜公司推荐 - 聚澜智能
  • 如何用 every 判断数组是否所有元素都满足特定条件
  • Spring AI 1.x 系列【25】结构化输出案例演示
  • XOutput完整指南:如何将旧游戏手柄转换为Xbox控制器
  • GeoAI赋能智慧城市:从交通优化到环境监测的实战解析