扫雷游戏(优化)

张开发
2026/6/10 0:56:19 15 分钟阅读
扫雷游戏(优化)
上篇所写的扫雷游戏即一个个位置猜展开看周围有几个雷但其实是有一种特殊情况是可以优化的就是周围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.有超出边界的风险必须给xi和yj设置边界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 (wincol*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 win0不能放在其他位置因为每次判断后如果win不等于10那么他的值是要清零的不可以影响到下一次扫雷时win的判断然后while是否继续循环的条件也不能用之前那个可以改成死循环win满足条件win10退出循环即可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)重新输入); } }其他地方与此前的扫雷程序没有区别仅仅是对细节进行一些优化

更多文章