• 《扫雷》的完善修改


    目录

    回顾:

    1.初始化两个数组:

    2.打印棋盘:

    3.布置雷:

    4.排查雷:

    正文:

    提出问题:

    解决问题:

    实现代码:

    总结:


    回顾:

    在之前的blog中,我们对扫雷的代码进行了编写,也初步实现了扫雷游戏的基本进程。

    具体的方式包含

    1.初始化两个数组:

    mine数组和show数组,一个是布置雷的数组,另一个则是显示棋盘的数组。

    mine数组初始化为字符0,show数组则初始化*。

    2.打印棋盘:

    对于棋盘的打印,我们先以mine数组为测试例子,将mine数组里的元素进行打印。要注意的是,我们不仅仅是打印棋盘,我们还对行和列,即横坐标和纵坐标进行了打印,方便玩家进行选择。

    3.布置雷:

    在雷的布置上,我们是选择在mine数组里面进行随机布置,既然是随机布置,就不得不用到srand函数

    1. x = rand() % row + 1;
    2. y = rand() % col + 1;
    3. srand((unsigned int) time(NULL)); //这条语句应当放在main函数里

    并且我们在布置雷的时候需要将mine数组里的(x,y)坐标赋值字符‘1’。

    4.排查雷:

    对于雷的排查,我们是定义了

    #define EASY_COUNT 10

    再定义一个 int win = 0;

    当排查一个坐标后,就让win++。这样当 win == (row * col - EASY_COUNT)时,便可以告诉玩家“排雷成功!”。

    以上就是对上一篇blog的初步回顾,详细的内容可以转到上篇blog:

    C语言实现《扫雷》_无双@的博客-CSDN博客

    也可以到我的代码仓库里面去寻找源码:

    Game with C: 这一仓库全部以c语言编写的小游戏 - Gitee.com

    正文:

    提出问题:

    首先我们要知道我们需要改进什么?

    如图:

    由图可知,坐标(1,1)周围的八个坐标都不存在雷,当我们排查该坐标时,也仅仅只是显示一个字符‘0’。

    但在window自带的扫雷游戏中,如果改坐标和该坐标周围都不存在雷时,它会展开一片空白的效果。

    如上图所示。

    那我们可不可以用现阶段学习的知识来实现展开一片空白的操作呢?

    答案是可以。

    可以运用递归解决。

    解决问题:

    为什么会想到用递归的方式来实现展开一片呢?

    其实当我们排查一个坐标(x,y)并判断此坐标的值为不为字符‘0’,如果是字符‘0’,我们就可以对他周围的(x-1,y)

    和(x-1,y+1)等坐标进行排查,直到排查到不等于‘0’的字符就停止,如此一来,递归操作就显得十分方便。

    实现代码:

    以下是实现该操作的伪代码,其中对排查雷的FindMine进行了略微修改,并在test.c文件的game()函数实现中,移除了while循环。

    1. //4.排查雷
    2. void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
    3. {
    4. int win = 0;
    5. int x = 0;
    6. int y = 0;
    7. while (win
    8. {
    9. printf("请输入要排查的坐标");
    10. scanf("%d%d", &x, &y);
    11. if (show[x][y] != '*')
    12. {
    13. printf("坐标重复!\n");
    14. continue;
    15. }
    16. if (x >= 1 && x <= row && y >= 1 && y <= col)
    17. {
    18. if (mine[x][y] == '1')
    19. {
    20. printf("很遗憾,你被炸死了\n");
    21. //把雷的位置打出来给玩家看
    22. DisplayBoard(mine, ROW, COL);
    23. break;
    24. }
    25. else
    26. {
    27. open(mine, show, x, y);
    28. DisplayBoard(show, ROW, COL);
    29. win++;
    30. }
    31. }
    32. else
    33. {
    34. printf("坐标非法,请重新输入\n");
    35. }
    36. }
    37. if (win == (row * col - EASY_COUNT))
    38. {
    39. printf("游戏获胜\n");
    40. DisplayBoard(mine, ROW, COL);
    41. }
    42. }
    43. int GetMineCount(char mine[ROWS][COLS], int x, int y)
    44. {
    45. return (mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1]
    46. + mine[x - 1][y] + mine[x + 1][y]
    47. + mine[x - 1][y + 1] + mine[x][y + 1] + mine[x + 1][y + 1])
    48. - 8 *'0';
    49. }
    50. static void open(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
    51. {
    52. if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
    53. {
    54. int count = GetMineCount(mine, x, y);
    55. if (count != 0)
    56. {
    57. show[x][y] = count + '0';
    58. }
    59. else if (show[x][y] != ' ')
    60. {
    61. show[x][y] = ' ';
    62. int i = 0;
    63. for (i = x - 1; i <= x + 1; i++)
    64. {
    65. int j = 0;
    66. for (j = y - 1; j <= y + 1; j++)
    67. {
    68. open(mine, show, i, j);
    69. }
    70. }
    71. }
    72. else
    73. {
    74. return;
    75. }
    76. }
    77. }

    这里我们单独分析open()函数
     

    1. static void open(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
    2. {
    3. if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
    4. {
    5. int count = GetMineCount(mine, x, y);
    6. if (count != 0)
    7. {
    8. show[x][y] = count + '0';
    9. }
    10. else if (show[x][y] != ' ')
    11. {
    12. show[x][y] = ' ';
    13. int i = 0;
    14. for (i = x - 1; i <= x + 1; i++)
    15. {
    16. int j = 0;
    17. for (j = y - 1; j <= y + 1; j++)
    18. {
    19. open(mine, show, i, j);
    20. }
    21. }
    22. }
    23. else
    24. {
    25. return;
    26. }
    27. }
    28. }

    以上代码就如我上边所描述的,选择排查坐标(x,y)时,如果此坐标为字符‘0’,即周围没有雷的存在,我们就可以进入open函数。

    图一是FindMine函数里的

    图二则是实现递归操作的方式

    接下来就可以实现递归操作,周围一个坐标一个坐标的传进去,直到排查到周围有雷就停止。

    运用两个for循环就可以遍历到(x,y)周围的八个坐标。

    如此便可以实现展开一片空白,这样则可以大大减少扫雷的复杂性,还可以让玩家获得成就感。

    代码演示:

    可以很明显的看到这一大片空白,就代表着这一片没有雷的存在。

    如此便可方便玩家。

    总结:

    此次blog利用了递归操作实现了对扫雷游戏的修改,使得游戏的可玩性大大提高。

    下来之后想查看源码则可以访问我的Gitee仓库:

    Game with C: 这一仓库全部以c语言编写的小游戏 - Gitee.com

    看懂这些代码还需要动手写一写。

    要记住:

    “坐而言不如起而行!”

    Actions speak louder than words!

  • 相关阅读:
    C++初阶(封装+多态--整理的自认为很详细)
    专业安卓实时投屏软件:极限投屏(QtScrcpy作者开发)使用说明
    Turtlebot2简单控制
    OpenGLES:绘制一个颜色渐变的圆
    【锂离子电池常见溶剂】
    WinccOA 学习笔记
    刷题指南,简洁扼要
    overleaf(Latex)的本地安装
    php 图片滑动验证 貳
    题解 [CF1682D] Circular Spanning Tree
  • 原文地址:https://blog.csdn.net/weixin_72917087/article/details/132874469