• 【C语言】扫雷----详解(扩展版)


    💓博客主页:江池俊的博客

    ⏩收录专栏:C语言初阶之路

    💻代码仓库:江池俊的代码仓库

    ✉️每一次努力都是一次进步,每一次尝试都是一次机会。无论遇到什么困难,都要坚定地向       前迈进。相信自己,并相信自己的潜力,您注定会取得非凡的成就!

    🍁 如果觉得博主的文章还不错的话,请点赞👍收藏🌟 三连支持一下博主💞

    🔥编译环境:Visual Studio 2022

    目录

    一、游戏介绍

    游戏规则: 

    游戏玩法:

    二、游戏实现思路 

    三、创建文件

    1.test.c文件 

    😆(menu)菜单函数的实现

    😆game函数的实现

    😆main函数的实现

    2.game.c文件

    😊书写初始化棋盘函数

    😊书写打印棋盘信息的函数

    😊书写设置雷的函数(是雷则为‘1’)

    😊书写统计周围雷个数的函数

    😊书写展开一片非雷区域的函数

    😊书写计算非雷和非标记的位置个数

    😊书写排查雷的函数

     3.game.h文件

    😄需要使用的头文件

    😄定义棋盘行列

    😄定义雷的个数

    😄初始化棋盘

    😄打印棋盘

    😄布置雷

    😄排查雷

    四、总代码 

    (一)game.h文件

    (二)game.c文件 

    (三)test.c文件

    五、效果展示


    前言

    本篇文章主要是讲解用C语言实现扫雷游戏,与三子棋的实现思路类似,可以参考我前面的两篇文章三子棋小游戏   猜数字小游戏

    下面我们回归正题,让我来详细讲解如何实现扫雷游戏。

    这里我们以9*9的网格为例。

    一、游戏介绍

    扫雷是一款经典的单人益智游戏,目标是在一个由方格组成的区域中找到并标记出所有的地雷,同时避免触雷。下面是扫雷游戏的网页链接,你可以通过玩下方的游戏加深自己对游戏的逻辑和原理的理解。

    扫雷游戏网页版 - Minesweeper

     5752a50bb6954d6f8fbe985d177d1c27.png   a8f8785734d640ad906c3fd72f1817de.png  402e368914154b67a1647f8558903392.png 

    上面依次是游戏进行、失败和胜利的界面 。

    游戏规则: 

    1.游戏开始时,整个区域被分割成一系列方格,其中一些方格中隐藏有地雷。

    2.方格可以是未被揭开的状态,也可以是已被揭开或标记过的状态。

    3.点击一个方格可以揭开它,如果该方格中没有地雷,则会显示数字,表示周围8个方格中地     雷的数量。

    4.如果揭开的方格没有地雷数量,则会自动会揭开周围相邻的空方格。

    5.如果揭开的方格中有地雷,游戏结束,玩家失败。

    游戏玩法:

     1.目标是找到并标记出所有的地雷,而不触雷。

     2.揭开方格时,根据方格周围的地雷数量,判断周围的方格是否安全。数字表示周围有多少颗地雷。

     3.如果您确定某个方格中有地雷,可以标记该方格为雷。这有助于您记住哪些方格是地雷,也可以帮助您避免不小心触雷。

     4.使用推理和逻辑来判断哪些方格一定是地雷,哪些方格一定是安全的。通过标记地雷并推断周围的数字,逐渐揭开更多的方格,直到找到所有的地雷。

    二、游戏实现思路 

    1.创建游戏棋盘:使用二维数组表示游戏棋盘,每个格子可以是开放状态、地雷或者标记状态。

    2.随机布雷:使用随机数生成地雷的位置,并在对应位置上设置地雷。

    3.计算周围地雷数量:遍历游戏棋盘,对于每个非地雷格子,统计周围八个格子中地雷的数量。

    4.游戏循环:进入游戏循环,每次循环包括以下步骤:
       a. 显示游戏棋盘。
       b. 接收用户输入,包括选择要打开的格子或标记地雷。
       c. 根据用户选择更新游戏棋盘状态。
       d. 检查游戏是否胜利或失败。

    5.判断游戏是否胜利:检查游戏棋盘中所有非地雷格子是否被正确打开。

    6.判断游戏是否失败:当玩家选择打开一个格子时,如果该格子是地雷,则游戏失败。

    7.标记地雷:当玩家选择标记一个格子时,在游戏棋盘中该格子的状态为已标记。

    8.打开格子:当玩家选择打开一个格子时,根据该格子的状态进行相应操作:
       a. 如果该格子已经被标记,则忽略。
       b. 如果该格子是地雷,则游戏失败。
       c. 如果该格子是数字格子,则显示该数字。
       d. 如果该格子是空白格子,则继续打开周围的空白格子直到遇到数字格子。(使用递归思想)

    10.继续游戏或退出:在游戏胜利或失败后,询问玩家是否继续游戏。

    三、创建文件

    由于该游戏的实现需要大量的代码,为了提高代码的可读性已经方便后续写代码时的自我检查,这里我们创建三个文件来实现该游戏,我们依次将三个文件命名为game.h \ game.c \ test.c。

    🌴game.h文件用来定义游戏棋盘的行列,以及包含该过程中需要用到的头文件和声明各种函数。

    🌴game.c文件最为重要,它主要是来写实现各种游戏功能的函数,即初始化棋盘,打印棋盘信息,设置棋盘雷的位置,统计雷的个数,展开无雷的一片区域,判断游戏输赢以及标记雷的位置。

    🌴test.c文件则是为了打印游戏菜单和实现game游戏函数。

    1.test.c文件 

    😆(menu)菜单函数的实现

    1. void menu()
    2. {
    3. printf("\t\t\t\t\t\t\t\t\t\t\t\n");
    4. printf("*********************\n");
    5. printf("***** 1. play *****\n");
    6. printf("***** 0. exit *****\n");
    7. printf("*********************\n");
    8. }

    打印结果: 

    😆game函数的实现

    主要功能如下:

    1.创建并初始化棋盘

    2.设置雷的位置(使用rand函数)

    3.打印棋盘信息

    4.排查雷:a.展开一片非雷区域

                      b.显示周围雷的个数

                      c.判断游戏输赢

    1. void game()
    2. {
    3. char mine[ROWS][COLS] = { 0 };//存放布置好的雷的信息
    4. char show[ROWS][COLS] = { 0 };//存放排查出的雷的信息
    5. //初始化数组的内容为指定内容
    6. //mine数组在没有布置雷的时候,都是‘0’
    7. InitBoard(mine, ROWS, COLS,'0');
    8. //show数组在没有排查雷的时候都是‘*’
    9. InitBoard(show, ROWS, COLS, '*');
    10. //设置雷
    11. Setmine(mine, ROW, COL);
    12. DisplayBoard(show, ROW, COL);
    13. //DisplayBoard(mine, ROW, COL);
    14. //排查雷
    15. FindMine(mine, show, ROW, COL);
    16. }

    这里我们需要创建两个数组作为棋盘,但是棋盘比实际的要大一圈,这是因为在对边上的格子进行排查时,往往不满八个格子,对9*9之外的格子访问时会越界,这时我们需要手动创建它周围的格子使得它能够成功访问,这样的话创建的数组棋盘就从9*9变成了11*11。

    当访问棋盘右上角的格子时,右上角黄色方框中的格子就是排查时要访问的格子

    这里我们要设置两个棋盘,其中一个棋盘(名字为mine)存放雷的信息,另一个棋盘(名字为show)存放排查雷的信息,这里我们初始化mine棋盘为字符‘0’,show棋盘为字符‘*’。

    打印结果:

    😆main函数的实现

    1. int main()
    2. {
    3. int input = 0;
    4. srand((unsigned int)time(NULL));
    5. do
    6. {
    7. menu();
    8. printf("请选择:>");
    9. scanf("%d", &input);
    10. switch (input)
    11. {
    12. case 1:system("cls"); game();
    13. break;
    14. case 0:printf("退出游戏\n");
    15. break;
    16. default:printf("选择错误,请重新输入!\n");
    17. break;
    18. }
    19. } while (input);
    20. return 0;
    21. }

    这里我们通过do while循环和switch语句来实现游戏的持续进行和对不同输入的选择,输入1,进入游戏,输入0,退出游戏,输入其他时,输出“选择错误,请重新输入!”。

    打印结果:

    2.game.c文件

    😊书写初始化棋盘函数

    1. //初始化棋盘
    2. void InitBoard(char board[ROWS][COLS], int rows, int cols,char set)
    3. {
    4. int i = 0;
    5. int j = 0;
    6. for(i=0;i
    7. for (j = 0; j < cols; j++)
    8. {
    9. board[i][j] = set;
    10. }
    11. }

    因为有两个棋盘,所以我们需要一个字符型变量(char)set 来设置棋盘初始化的值,如果是mine棋盘,则 set = ‘0’;如果是show棋盘,则 set = ‘*’ 。

    😊书写打印棋盘信息的函数

    1. //打印棋盘信息
    2. void DisplayBoard(char board[ROWS][COLS], int row, int col)
    3. {
    4. int i = 0;
    5. int j = 0;
    6. printf("------扫雷游戏------\n");
    7. printf("════════════════════\n");//美化棋盘
    8. for (j = 0; j <= col; j++)
    9. {
    10. printf("%d|", j);
    11. }
    12. printf("\n-|══════════════════");//美化棋盘
    13. printf("\n");
    14. for (i = 1; i <= row; i++)
    15. {
    16. printf("%d|", i);
    17. for (j = 1; j <= col; j++)
    18. {
    19. printf("%c|", board[i][j]);
    20. }
    21. printf("\n");
    22. }
    23. printf("════════════════════\n");//美化棋盘
    24. printf("------扫雷游戏------\n\n");
    25. }

    打印结果: 

    😊书写设置雷的函数(是雷则为‘1’)

    1. //设置雷的函数
    2. void Setmine(char board[ROWS][COLS], int row, int col)
    3. {
    4. int count = EASY_COUNT;
    5. //行1-9 列1-9
    6. while (count)
    7. {
    8. int x = rand() % row + 1;
    9. int y = rand() % col + 1;
    10. if (board[x][y] == '0')
    11. {
    12. board[x][y] = '1';
    13. count--;
    14. }
    15. }
    16. }

    下面我会针对遇到的问题进行解答👀

    👀如何随机设置雷的位置? 

    使用srand()来随机设置雷的坐标

    1. //test.c
    2. srand((unsigned int)time(NULL));//设置随机数的生成起点

     👀如何控制雷的坐标位置合理

    1. int x = rand() % row + 1;//生成1-9的随机数
    2. int y = rand() % col + 1;//生成1-9的随机数

    利用rand() 函数取row或col的模再+1来得到1-9的随机数,这样就可以控制雷的位置在棋盘上。

    😊书写统计周围雷个数的函数

    1. //统计周围雷数的函数
    2. int get_mine_count(char board[ROWS][COLS],int x,int y)
    3. {
    4. int count = 0;
    5. for(int i=-1;i<=1;i++)
    6. for (int j = -1; j <= 1; j++)
    7. {
    8. if (board[x + i][y + j] == '1')
    9. count++;
    10. }
    11. return count;
    12. /*return (board[x - 1][y] +
    13. board[x - 1][y - 1] +
    14. board[x][y - 1] +
    15. board[x + 1][y - 1] +
    16. board[x + 1][y] +
    17. board[x + 1][y + 1] +
    18. board[x][y + 1] +
    19. board[x - 1][y + 1] - 8 * '0');*/
    20. }

    当排查的位置为x,y时,根据上图可知周围八个格子的坐标,计算周围雷的个数,当这八个位置每有一个雷时我们就加一。

    😊书写展开一片非雷区域的函数

    1. //递归,展开一片区域的函数
    2. void OpenArea(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col,int x, int y)
    3. {
    4. int count = get_mine_count(mine, x, y);
    5. if (count == 0)
    6. {
    7. show[x][y] = ' ';
    8. for (int i = x - 1; i <= x + 1; i++)
    9. {
    10. for (int j = y - 1; j <= y + 1; j++)
    11. {
    12. if (show[i][j] == '*' && x >= 1 && x <= row && y >= 1 && y <= col)
    13. {
    14. OpenArea(mine, show,ROW,COL, i, j);
    15. }
    16. }
    17. }
    18. }
    19. else
    20. {
    21. show[x][y] = count + '0';
    22. }
    23. }

     因为需要对存储雷位置的棋盘和显示棋盘信息的棋盘进行操作,所以形参中需要两个棋盘。

    当周围没有雷时,将此位置的show棋盘上显示为 ‘  ’ (空格),同时对周围八个坐标位置的格子进行判断,如果这些坐标(合理)在9*9的棋盘上,则再次对他们进行同样的判断,此时就需要利用递归的思想(即再次调用展开一片非雷区域的函数);当周围有雷,这时就需要统计雷的个数,并将雷的个数显示在show棋盘上。

    注意:

    因为show棋盘上存储的是字符(char),而统计的数是整型,所以我们需要将整型转换为字符型(即让数字加上字符‘0’)。

    😊书写计算非雷和非标记的位置个数

    1. //计算非雷和非标记的位置个数
    2. int get_win(char board[ROWS][COLS], int row, int col)
    3. {
    4. int win = 0;
    5. for(int i=1;i<=row;i++)
    6. for (int j = 1; j <= col; j++)
    7. {
    8. if (board[i][j]!='*'&&board[i][j]!='!')
    9. win++;
    10. }
    11. return win;
    12. }

    该函数作用是为了判断游戏输赢。 

    😊书写排查雷的函数

    1. //排雷的函数
    2. void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
    3. {
    4. //1.输入排查的坐标
    5. //2.检查该坐标处是不是雷
    6. //(1) 是雷 - 很遗憾,你被炸死了 - 游戏结束
    7. //(2) 不是雷 - 统计坐标周围有几个雷 - 存储排查雷的信息到show数组,游戏继续
    8. int x = 0;
    9. int y = 0;
    10. int win = 0;
    11. int select = 0;
    12. while (win < row * col - EASY_COUNT)
    13. {
    14. printf("请选择:1.排查雷 2.标记雷 3.取消标记\t");
    15. scanf("%d", &select);
    16. if (select == 1)
    17. {
    18. printf("请输入要排查雷的坐标:>");
    19. scanf("%d %d", &x, &y);
    20. //判断坐标合法性
    21. if (x >= 1 && x <= row && y >= 1 && y <= col)
    22. {
    23. if (show[x][y] == '*')
    24. {
    25. if (mine[x][y] == '1')
    26. {
    27. printf("\n\n很遗憾,你被炸死了!\n");
    28. printf("雷的分布情况,其中('1'表示雷):\n");
    29. DisplayBoard(mine, ROW, COL);
    30. break;
    31. }
    32. else
    33. {
    34. OpenArea(mine, show,ROW,COL, x, y);
    35. //显示排查出的信息
    36. DisplayBoard(show, ROW, COL);
    37. //计算已经排出的非雷位置的个数
    38. win = get_win(show, ROW, COL);
    39. }
    40. }
    41. else
    42. {
    43. printf("该位置已被排查过,请重新输入!\n");
    44. }
    45. }
    46. else
    47. {
    48. printf("坐标不合法,请重新输入!\n");
    49. }
    50. }
    51. else if (select == 2)
    52. {
    53. printf("请输入要标记的坐标:>");
    54. scanf("%d %d", &x, &y);
    55. //判断坐标合法性
    56. if (x >= 1 && x <= row && y >= 1 && y <= col)
    57. {
    58. if (show[x][y] == '*')
    59. {
    60. show[x][y] = '!';
    61. DisplayBoard(show, ROW, COL);
    62. }
    63. else if(show[x][y]=='!')
    64. {
    65. printf("该位置已被标记,请重新选择!\n");
    66. }
    67. else
    68. {
    69. printf("该位置不能标记,请重新选择!\n");
    70. }
    71. }
    72. else
    73. {
    74. printf("坐标不合法,请重新输入!\n");
    75. }
    76. }
    77. else if (select == 3)
    78. {
    79. printf("请输入要取消标记的坐标:>");
    80. scanf("%d %d", &x, &y );
    81. if (x >= 1 && x <= row && y >= 1 && y <= col)
    82. {
    83. if (show[x][y] == '!')
    84. {
    85. show[x][y] = '*';
    86. DisplayBoard(show, ROW, COL);
    87. }
    88. else
    89. {
    90. printf("该位置不能取消标记,请重新选择!\n");
    91. }
    92. }
    93. else
    94. {
    95. printf("坐标不合法,请重新输入!\n");
    96. }
    97. }
    98. else
    99. {
    100. printf("输入有误,请重新输入!\n");
    101. }
    102. //printf("win=%d\n", win);
    103. }
    104. if (win == row * col - EASY_COUNT)
    105. {
    106. printf("\n恭喜你,排雷成功!\n");
    107. printf("雷的分布情况,其中('1'表示雷):\n");
    108. DisplayBoard(mine, ROW, COL);
    109. }
    110. }
    111. //基础功能+拓展功能
    112. //1.标记功能(用'!')
    113. //2.展开一片区域的功能(使用递归)
    114. //*当排查下x,y坐标时:(1)该坐标不是雷 (2)该坐标周围没有雷 (3)该坐标没有被排查过

    👀如何排查雷? 

    基本思路:

                    1.输入排查的坐标
                    2.检查该坐标处是不是雷
                      ❌ 是雷   - 很遗憾,你被炸死了 - 游戏结束
                      ✔️不是雷 - 统计坐标周围有几个雷 - 存储排查雷的信息到show数组,游戏继续

    1. printf("请输入要排查雷的坐标:>");
    2. scanf("%d %d", &x, &y);
    3. //判断坐标合法性
    4. if (x >= 1 && x <= row && y >= 1 && y <= col)
    5. {
    6. if (show[x][y] == '*')
    7. {
    8. if (mine[x][y] == '1')
    9. {
    10. printf("\n\n很遗憾,你被炸死了!\n");
    11. printf("雷的分布情况,其中('1'表示雷):\n");
    12. DisplayBoard(mine, ROW, COL);
    13. break;
    14. }
    15. else
    16. {
    17. OpenArea(mine, show,ROW,COL, x, y);
    18. //显示排查出的信息
    19. DisplayBoard(show, ROW, COL);
    20. //计算已经排出的非雷位置的个数
    21. win = get_win(show, ROW, COL);
    22. //win++;
    23. }
    24. }
    25. else
    26. {
    27. printf("该位置已被排查过,请重新输入!\n");
    28. }
    29. }
    30. else
    31. {
    32. printf("坐标不合法,请重新输入!\n");
    33. }

    👀如何标记雷? 

    因为排查雷和标记雷是两个不同的过程,所以这时我们需要通过使用if-else语句来选择排查雷还是标记雷,标记雷的位置用‘ !’来表示。

    1. //printf("请选择:1.排查雷 2.标记雷\t");
    2. //scanf("%d", &select);
    3. else if (select == 2)
    4. {
    5. printf("请输入要标记的坐标:>");
    6. scanf("%d %d", &x, &y);
    7. //判断坐标合法性
    8. if (x >= 1 && x <= row && y >= 1 && y <= col)
    9. {
    10. if (show[x][y] == '*')
    11. {
    12. show[x][y] = '!';
    13. DisplayBoard(show, ROW, COL);
    14. }
    15. else if(show[x][y]=='!')
    16. {
    17. printf("该位置已被标记,请重新选择!\n");
    18. }
    19. else
    20. {
    21. printf("该位置不能标记,请重新选择!\n");
    22. }
    23. }
    24. else
    25. {
    26. printf("坐标不合法,请重新输入!\n");
    27. }
    28. }
    29. else
    30. {
    31. printf("输入有误,请重新输入!\n");
    32. }
    33. //printf("win=%d\n", win);
    34. }

    👀 如何判断输赢?

    1. if (win == row * col - EASY_COUNT)
    2. {
    3. printf("\n恭喜你,排雷成功!\n");
    4. printf("雷的分布情况,其中('1'表示雷):\n");
    5. DisplayBoard(mine, ROW, COL);
    6. }

    当show棋盘上非雷位置和非标记位置个数mine棋盘上‘0’的个数(即非雷个数)相等时,打印“恭喜你,排雷成功!”,并打印mine棋盘的雷的分布情况。若不等于则继续进行排雷或标记雷的步骤。

    打印结果: 

     

     3.game.h文件

    😄需要使用的头文件

    1. #include
    2. #include
    3. #include;

    😄定义棋盘行列

    1. #define ROW 9
    2. #define COL 9
    3. #define ROWS ROW+2
    4. #define COLS COL+2

    打印棋盘信息时,使用9*9的棋盘,在进行初始化,设置雷,排查雷,标记雷等操作时使用11*11的棋盘。

    😄定义雷的个数

    #define EASY_COUNT 10

    😄初始化棋盘

    1. //初始化棋盘
    2. void InitBoard(char board[ROWS][COLS], int rows, int cols,char set);

    😄打印棋盘

    1. //打印棋盘
    2. void DisplayBoard(char board[ROWS][COLS], int row, int col);

    😄布置雷

    1. //布置雷
    2. void Setmine(char board[ROWS][COLS],int row,int col);

    😄排查雷

    1. //排查雷
    2. void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS],int row,int col);

    四、总代码 

    注意:此代码分为三个部分的代码

    (一)game.h文件

    1. #include
    2. #include
    3. #include;
    4. #define ROW 9
    5. #define COL 9
    6. #define ROWS ROW+2
    7. #define COLS COL+2
    8. #define EASY_COUNT 10
    9. //初始化棋盘
    10. void InitBoard(char board[ROWS][COLS], int rows, int cols,char set);
    11. //打印棋盘
    12. void DisplayBoard(char board[ROWS][COLS], int row, int col);
    13. //布置雷
    14. void Setmine(char board[ROWS][COLS],int row,int col);
    15. //排查雷
    16. void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS],int row,int col);

    (二)game.c文件 

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include"game.h"
    3. //初始化棋盘
    4. void InitBoard(char board[ROWS][COLS], int rows, int cols,char set)
    5. {
    6. int i = 0;
    7. int j = 0;
    8. for(i=0;i
    9. for (j = 0; j < cols; j++)
    10. {
    11. board[i][j] = set;
    12. }
    13. }
    14. //打印棋盘信息
    15. void DisplayBoard(char board[ROWS][COLS], int row, int col)
    16. {
    17. int i = 0;
    18. int j = 0;
    19. printf("------扫雷游戏------\n");
    20. printf("════════════════════\n");//美化棋盘
    21. for (j = 0; j <= col; j++)
    22. {
    23. printf("%d|", j);
    24. }
    25. printf("\n-|══════════════════");//美化棋盘
    26. printf("\n");
    27. for (i = 1; i <= row; i++)
    28. {
    29. printf("%d|", i);
    30. for (j = 1; j <= col; j++)
    31. {
    32. printf("%c|", board[i][j]);
    33. }
    34. printf("\n");
    35. }
    36. printf("════════════════════\n");//美化棋盘
    37. printf("------扫雷游戏------\n\n");
    38. }
    39. //设置雷的函数
    40. void Setmine(char board[ROWS][COLS], int row, int col)
    41. {
    42. int count = EASY_COUNT;
    43. //行1-9 列1-9
    44. while (count)
    45. {
    46. int x = rand() % row + 1;
    47. int y = rand() % col + 1;
    48. if (board[x][y] == '0')
    49. {
    50. board[x][y] = '1';
    51. count--;
    52. }
    53. }
    54. }
    55. //统计周围雷数的函数
    56. int get_mine_count(char board[ROWS][COLS],int x,int y)
    57. {
    58. int count = 0;
    59. for(int i=-1;i<=1;i++)
    60. for (int j = -1; j <= 1; j++)
    61. {
    62. if (board[x + i][y + j] == '1')
    63. count++;
    64. }
    65. return count;
    66. /*return (board[x - 1][y] +
    67. board[x - 1][y - 1] +
    68. board[x][y - 1] +
    69. board[x + 1][y - 1] +
    70. board[x + 1][y] +
    71. board[x + 1][y + 1] +
    72. board[x][y + 1] +
    73. board[x - 1][y + 1] - 8 * '0');*/
    74. }
    75. //递归,展开一片区域的函数
    76. void OpenArea(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col,int x, int y)
    77. {
    78. int count = get_mine_count(mine, x, y);
    79. if (count == 0)
    80. {
    81. show[x][y] = ' ';
    82. for (int i = x - 1; i <= x + 1; i++)
    83. {
    84. for (int j = y - 1; j <= y + 1; j++)
    85. {
    86. if (show[i][j] == '*' && x >= 1 && x <= row && y >= 1 && y <= col)
    87. {
    88. OpenArea(mine, show,ROW,COL, i, j);
    89. }
    90. }
    91. }
    92. }
    93. else
    94. {
    95. show[x][y] = count + '0';
    96. }
    97. }
    98. // 计算非雷和非标记的位置个数
    99. int get_win(char board[ROWS][COLS], int row, int col)
    100. {
    101. int win = 0;
    102. for(int i=1;i<=row;i++)
    103. for (int j = 1; j <= col; j++)
    104. {
    105. if (board[i][j]!='*'&&board[i][j]!='!')
    106. win++;
    107. }
    108. return win;
    109. }
    110. //排雷的函数
    111. void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
    112. {
    113. //1.输入排查的坐标
    114. //2.检查该坐标处是不是雷
    115. //(1) 是雷 - 很遗憾,你被炸死了 - 游戏结束
    116. //(2) 不是雷 - 统计坐标周围有几个雷 - 存储排查雷的信息到show数组,游戏继续
    117. int x = 0;
    118. int y = 0;
    119. int win = 0;
    120. int select = 0;
    121. while (win < row * col - EASY_COUNT)
    122. {
    123. printf("请选择:1.排查雷 2.标记雷 3.取消标记\t");
    124. scanf("%d", &select);
    125. if (select == 1)
    126. {
    127. printf("请输入要排查雷的坐标:>");
    128. scanf("%d %d", &x, &y);
    129. //判断坐标合法性
    130. if (x >= 1 && x <= row && y >= 1 && y <= col)
    131. {
    132. if (show[x][y] == '*')
    133. {
    134. if (mine[x][y] == '1')
    135. {
    136. printf("\n\n很遗憾,你被炸死了!\n");
    137. printf("雷的分布情况,其中('1'表示雷):\n");
    138. DisplayBoard(mine, ROW, COL);
    139. break;
    140. }
    141. else
    142. {
    143. OpenArea(mine, show,ROW,COL, x, y);
    144. //显示排查出的信息
    145. DisplayBoard(show, ROW, COL);
    146. //计算已经排出的非雷位置的个数
    147. win = get_win(show, ROW, COL);
    148. }
    149. }
    150. else
    151. {
    152. printf("该位置已被排查过,请重新输入!\n");
    153. }
    154. }
    155. else
    156. {
    157. printf("坐标不合法,请重新输入!\n");
    158. }
    159. }
    160. else if (select == 2)
    161. {
    162. printf("请输入要标记的坐标:>");
    163. scanf("%d %d", &x, &y);
    164. //判断坐标合法性
    165. if (x >= 1 && x <= row && y >= 1 && y <= col)
    166. {
    167. if (show[x][y] == '*')
    168. {
    169. show[x][y] = '!';
    170. DisplayBoard(show, ROW, COL);
    171. }
    172. else if(show[x][y]=='!')
    173. {
    174. printf("该位置已被标记,请重新选择!\n");
    175. }
    176. else
    177. {
    178. printf("该位置不能标记,请重新选择!\n");
    179. }
    180. }
    181. else
    182. {
    183. printf("坐标不合法,请重新输入!\n");
    184. }
    185. }
    186. else if (select == 3)
    187. {
    188. printf("请输入要取消标记的坐标:>");
    189. scanf("%d %d", &x, &y );
    190. if (x >= 1 && x <= row && y >= 1 && y <= col)
    191. {
    192. if (show[x][y] == '!')
    193. {
    194. show[x][y] = '*';
    195. DisplayBoard(show, ROW, COL);
    196. }
    197. else
    198. {
    199. printf("该位置不能取消标记,请重新选择!\n");
    200. }
    201. }
    202. else
    203. {
    204. printf("坐标不合法,请重新输入!\n");
    205. }
    206. }
    207. else
    208. {
    209. printf("输入有误,请重新输入!\n");
    210. }
    211. //printf("win=%d\n", win);
    212. }
    213. if (win == row * col - EASY_COUNT)
    214. {
    215. printf("\n恭喜你,排雷成功!\n");
    216. printf("雷的分布情况,其中('1'表示雷):\n");
    217. DisplayBoard(mine, ROW, COL);
    218. }
    219. }
    220. //基础功能+拓展功能
    221. //1.标记功能(用'!')
    222. //2.展开一片区域的功能(使用递归)
    223. //*当排查下x,y坐标时:(1)该坐标不是雷 (2)该坐标周围没有雷 (3)该坐标没有被排查过

    (三)test.c文件

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include"game.h"
    3. void menu()
    4. {
    5. printf("\t\t\t\t\t\t\t\t\t\t\t\n");
    6. printf("*********************\n");
    7. printf("***** 1. play *****\n");
    8. printf("***** 0. exit *****\n");
    9. printf("*********************\n");
    10. }
    11. void game()
    12. {
    13. char mine[ROWS][COLS] = { 0 };//存放布置好的雷的信息
    14. char show[ROWS][COLS] = { 0 };//存放排查出的雷的信息
    15. //初始化数组的内容为指定内容
    16. //mine数组在没有布置雷的时候,都是‘0’
    17. InitBoard(mine, ROWS, COLS,'0');
    18. //show数组在没有排查雷的时候都是‘*’
    19. InitBoard(show, ROWS, COLS, '*');
    20. //设置雷
    21. Setmine(mine, ROW, COL);
    22. DisplayBoard(show, ROW, COL);
    23. //DisplayBoard(mine, ROW, COL);
    24. //排查雷
    25. FindMine(mine, show, ROW, COL);
    26. }
    27. int main()
    28. {
    29. int input = 0;
    30. srand((unsigned int)time(NULL));
    31. do
    32. {
    33. menu();
    34. printf("请选择:>");
    35. scanf("%d", &input);
    36. switch (input)
    37. {
    38. case 1:system("cls"); game();
    39. break;
    40. case 0:printf("退出游戏\n");
    41. break;
    42. default:printf("选择错误,请重新输入!\n");
    43. break;
    44. }
    45. } while (input);
    46. return 0;
    47. }

    五、效果展示

    扫雷游戏展示

    扫雷游戏展示

    🔥好了, 今天的内容就分享到这里了。愿这篇博客能够为您带来新的思考和启示。感谢您的耐心阅读和支持。无论在人生的道路上遇到怎样的困难和挑战,记住相信自己的力量,努力前行。期待与您共同探索更多精彩的内容。再次感谢!

  • 相关阅读:
    【从零开始学习深度学习】7.自己动手实现softmax回归的训练与预测
    TiDB Lightning 并行导入
    JavaScript 基础知识| 数据类型|类型转换
    档案信息化咨询方法论实践要点有哪些?
    day31-JQuery04
    超实用!推荐5款办公黑科技软件,用了就离不开
    二叉树题目:二叉树寻路
    “AI大模型革新浪潮:农业、生态、气象科研的新智能助手,开启智慧科研新篇章!“
    [vue3] 使用ElementPlus页面布局搭建架子
    UIC 564-2 座椅耐火测试
  • 原文地址:https://blog.csdn.net/2201_75743654/article/details/131636089