当前位置:   article > 正文

C语言基础:扫雷游戏的C语言实现(超详图解+源码)_扫雷c语言程序设计

扫雷c语言程序设计

友友们好,今天和大家一起做一个简单的C语言小游戏——扫雷小游戏。

  游戏规则如下:

       扫雷的规则很简单。盘面上有许多方格,方格中随机分布着一些雷。你的目标是避开雷,打开其他所有格子。一个非雷格中的数字表示其相邻8格中的雷数,你可以利用这个信息推导出安全格和雷的位置。打开所有安全格将被判定为胜利,打开雷将被判定为失败。


目录

实现思路

一、制作一个游戏菜单

二、构建游戏的基本逻辑结构

三、进入游戏的制作

1、定义两个一样的数组

​编辑

2、初始化数组

3、打印盘面

4、布置雷

5、排查雷

·这个坐标不是雷,提示周围有几个雷

·这个坐标是雷,游戏结束   

·所有非雷位置都找到了,游戏胜利

6、game函数的实现

四、扫雷游戏的实现


实现思路

       首先,制作一个游戏菜单,而后构建整个游戏的基本逻辑结构,然后进入游戏的制作。首先要在盘面上随机给出10个雷的位置; 然后玩家需要在盘面的合法位置排雷,如果在非法位置,应给出相应提示;在排雷的同时要判断游戏是否结束,如果结束需要判断胜负。

       接下来我们就以这个基本思路来进行代码的实现。


一、制作一个游戏菜单

首先,我们要制作一个游戏菜单。我们用一个简易的函数来实现他。

  1. void menu()
  2. {
  3. printf("*********************************\n");
  4. printf("******* 扫雷小游戏 *********\n");
  5. printf("******* 1、play *********\n");
  6. printf("******* 0、exit *********\n");
  7. printf("*********************************\n");
  8. }

我们在主函数中可以调用这个函数来实现打印菜单的目的。


二、构建游戏的基本逻辑结构

制作完菜单后,我们需要构建这个游戏的基本逻辑结构。

首先需要明确我们的需求: 1、我们可以通过输入 1 / 0 来选择开始或结束游戏

                                            2、如果一把玩完不过瘾,我们可以通过选择来再玩一把

· 我们运用分支语句的知识来实现第一个需求。

       在这里我使用switch语句,定义一个整型来存放输入的数字,如果输入的数字是 1 ,则提示“开始游戏”;如果输入的数字是 0 ,则提示“结束游戏”;如果输入了 1/0 以外的数字,则我们提醒他输错了,重新输入。

· 我们通过循环来实现第二个需求。

       在这里使用do... while() 循环,将定义的整型放在() 里作为判断条件。当我们输入 1 ,为非0,判断为真,游戏继续;当我们输入 0 ,判断为假,游戏结束;当我们输入 1/0  以外的数字,为非0,判断为真,可以继续循环让我们重新判断。

  1. int main()
  2. {
  3. int input;
  4. //先输入一个input判断要不要进入游戏,将其也设为循环的判断条件
  5. do {
  6. menu();
  7. printf("请输入->");
  8. scanf("%d", &input);
  9. switch (input)
  10. {
  11. case 1:
  12. printf("开始游戏\n");
  13. game();
  14. //如果输入1,说明要玩游戏,封装一个game函数来包含游戏内容
  15. break;
  16. case 0:
  17. printf("退出游戏\n");
  18. break;
  19. default:
  20. printf("输错啦,请重新输入\n");
  21. break;
  22. }
  23. } while (input);
  24. return 0;
  25. }


从代码运行结果来看,满足了我们提出的两点需求。


三、进入游戏的制作

1、定义两个一样的数组

两个数组,一个展示,一个放雷

  所以我们需要定义两个 11*11的数组,一个用来存放雷的数据,一个用来显示。

 为了后期调试的方便,我们可以将数组参数使用#define标识符替换列表中的参数。

  1. #include<stdio.h>
  2. #include<stdlib.h> //srand函数的头文件
  3. #include<time.h> //time函数的头文件
  4. #define ROW 9 //实际使用的行
  5. #define COL 9 //实际使用的列
  6. #define ROWS 11 //数组使用的行
  7. #define COLS 11 //数组使用的列
  8. #define COUNT_EASY 10
  9. //简单版本有10个雷

2、初始化数组

       首先我们封装一个game函数,将实现游戏的内容都放在game函数中。定义两个字符型的二维数组,将二者初始化。

  1. //初始化数组
  2. void InitBoard(char board[ROWS][COLS], int rows, int cols, char ret)
  3. {
  4. int x = 0;
  5. int y = 0;
  6. for (x = 0; x < rows; x++)
  7. {
  8. for (y = 0; y < cols; y++)
  9. {
  10. board[x][y] = ret;
  11. }
  12. }
  13. }
  14. void game()
  15. {
  16. //为了方便,把两个数组定义成完全一样的
  17. char mine[ROWS][COLS] = { 0 };
  18. char show[ROWS][COLS] = { 0 };
  19. //初始化两个数组,传对应的参数进去
  20. //将雷盘先全都定义为0
  21. //将显示盘定义为*
  22. InitBoard(mine, ROWS, COLS, '0');
  23. InitBoard(show, ROWS, COLS, '*');
  24. }

3、打印盘面

我们先清楚盘面的格式为:11 * 11 的正方形;其中只需打印中间的9*9,所以我们传ROW与COL进去即可;为了格式好看与查找方便,我们还可以添加一些表头与分隔。

            

  1. //打印棋盘
  2. void DisplayBoard(char board[ROWS][COLS], int row, int col)
  3. {
  4. int x = 0;
  5. int y = 0;
  6. printf("--------扫雷---------\n");
  7. for (x = 0; x <= row; x++)
  8. {
  9. printf(" %d", x); //打印坐标提示行
  10. }
  11. printf("\n");
  12. for (x = 1; x <= row; x++)
  13. {
  14. printf(" %d", x); //打印坐标提示列
  15. for (y = 1; y <= col; y++)
  16. {
  17. printf(" %c", board[x][y]);
  18. }
  19. printf("\n");
  20. }
  21. printf("---------------------\n");
  22. }
  23. //打印的时候传过去的数组还是11*11的,数组是不会变的,不会因为你想打印的是9*9的就变成9*9的数组
  24. //因为我们只想打印出9*9的格子,所以传过去的是ROW和COL

4、布置雷

       简易版的9*9盘面内有10个雷,我们可以用rand函数来生成随机值来作为雷生成的坐标。生成雷时需要注意,雷的坐标需要是一个合法坐标,我们可以将生成坐标的过程放进循环里,当雷的坐标为合法坐标时跳出循环。注意将坐标适当处理。我们封装一个函数,在game函数中调用来实现该功能。

  1. //布置雷
  2. void Setmine(char board[ROWS][COLS], int row, int col)
  3. {
  4. int x = 0;
  5. int y = 0;
  6. int count = COUNT_EASY; //雷的数量
  7. while (count)//当没布置完雷之前都继续循环
  8. {
  9. x = rand() % row + 1; //生成数%row后范围是0~8 我们需要的是1~9
  10. y = rand() % col + 1;
  11. if (board[x][y] == '0')
  12. {
  13. board[x][y] = '1';
  14. count--;
  15. }
  16. }
  17. }

  注意:

       C语言中提供了一个rand函数可以帮我们生成随机数,返回值为int 整型,返回的值就是一个随机数。但rand函数生成的是伪随机数,返回的随机值并不完全随机。

                        

       rand函数在生成随机数之前,要使用srand函数设置随机数的生成器。srand()括号中放置类似于生成随机数的种子,种子固定了生成的随机数也是固定的。所以我们要使括号中的值为随机变化的,才能使产生的数值为随机值。

       在我们的计算机中,时间是时刻在发生变化的,如果能将时间传入srand中,那么就可以实现真正的随机。这个时候我们可以使用time函数来解决这个问题。

   

       time函数可以返回一个时间戳,时间戳是一串数字, 是随着时间在不断变化的 。在使用时我们需要调用二者的头文件。time函数的返回类型是time_t,在srand中要使用他需要强制类型转换为(unsigned int)

所以在主函数中:

  1. //记得引用头文件
  2. #include<stdio.h>
  3. #include<stdlib.h> //srand函数的头文件
  4. #include<time.h> //time函数的头文件
  5. int main()
  6. {
  7. srand((unsigned int)time(NULL));
  8. int input = 0;
  9. do {
  10. menu();
  11. printf("请输入->");
  12. scanf("%d", &input);
  13. switch (input)
  14. {
  15. case 1:
  16. printf("开始游戏\n");
  17. game();
  18. break;
  19. case 0:
  20. printf("退出游戏\n");
  21. break;
  22. default:
  23. printf("输错了,请重新输入\n");
  24. break;
  25. }
  26. } while (input);
  27. return 0;
  28. }

这样就能实现随机布置雷:

     

5、排查雷

       首先玩家排查雷需要在盘面中的合法位置,如果排查位置在盘外或者排查的位置已被占用,我们需要给出相应的提示。然后玩家给出的是盘面的坐标位置,因为我们盘面坐标刚好和数组位置对应,所以可以不用再进行操作。我们封装一个函数,在game函数中调用来实现该功能。

       并且在排查的过程中,可能出现以下几种情况:1、这个坐标不是雷,提示周围有几个雷

                                                                                   2、这个坐标是雷,游戏结束   

                                                                                   3、所有非雷位置都找到了,游戏胜利

       如果找到的坐标位置为非雷,那么我们就需要继续排查,所以我们将排查过程放到循环中进行,踩到雷或者排查结束才跳出循环。

·这个坐标不是雷,提示周围有几个雷

所以我们可以通过以下代码来实现功以上功能:

  1. //数周围有几个雷
  2. int GetMineCount(char mine[ROWS][COLS], int x, int y)
  3. {
  4. return (mine[x - 1][y - 1] +
  5. mine[x][y - 1] +
  6. mine[x + 1][y - 1] +
  7. mine[x + 1][y] +
  8. mine[x + 1][y + 1] +
  9. mine[x][y + 1] +
  10. mine[x - 1][y + 1] +
  11. mine[x - 1][y]) - (8 * '0');
  12. }

       然后在game函数中调用,实现函数功能。

·这个坐标是雷,游戏结束   

       当踩到雷时,我们给出相应提示后直接跳出循环结束游戏即可。

·所有非雷位置都找到了,游戏胜利

       我们可以设置一个整型变量,其大小为非雷的位置个数。如果成功排除一个雷就将其减一,将他作为循环的判断条件,当他减为0时刚好也能跳出循环,并给出相应提示表示排雷成功。

  1. //排查雷
  2. void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
  3. {
  4. int x = 0;
  5. int y = 0;
  6. int win = row * col - COUNT_EASY;
  7. while (win )
  8. {
  9. printf("请输入要排查的坐标->");
  10. scanf("%d %d", &x, &y);
  11. if (x >= 1 && x <= row && y >= 1 && y <= col)
  12. {
  13. if (mine[x][y] == '1')
  14. {
  15. printf("踩到雷啦!爆炸!\n");
  16. DisplayBoard(mine, row, col);
  17. break;
  18. }
  19. else if (show[x][y] != '*')
  20. {
  21. printf("排查过该坐标,请重新输入\n");
  22. }
  23. else if (mine[x][y] == '0')
  24. {
  25. int ret = 0;
  26. ret = GetMineCount(mine, x, y);
  27. show[x][y] = ret + '0';
  28. DisplayBoard(show, ROW, COL);
  29. win--;
  30. }
  31. }
  32. else
  33. {
  34. printf("输入坐标非法,请重新输入\n");
  35. }
  36. }
  37. //跳出循环有两种可能,一个是踩雷退出,一个是排雷完成退出
  38. //需要判断是不是排雷成功,然后给出提示
  39. if(win==0)
  40. printf("恭喜你,排雷成功! \n");
  41. }

6、game函数的实现

  1. void game()
  2. {
  3. //为了方便,把两个数组定义成完全一样的
  4. char mine[ROWS][COLS] = { 0 };
  5. char show[ROWS][COLS] = { 0 };
  6. //初始化两个数组
  7. InitBoard(mine, ROWS, COLS, '0');
  8. InitBoard(show, ROWS, COLS, '*');
  9. //打印棋盘
  10. //DisplayBoard(mine, ROW, COL);
  11. //对应雷的数组不需要给玩家看
  12. DisplayBoard(show, ROW, COL);
  13. //布置雷
  14. Setmine(mine, ROW, COL);
  15. //DisplayBoard(mine, ROW, COL);
  16. //排查雷
  17. Findmine(mine, show, ROW, COL);
  18. }


四、扫雷游戏的实现

将上面的代码汇总成一个完整的扫雷游戏:

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<time.h>
  4. #define ROW 9
  5. #define COL 9
  6. #define ROWS 11
  7. #define COLS 11
  8. #define COUNT_EASY 10
  9. //简单版本有10个雷
  10. void menu()
  11. {
  12. printf("*********************************\n");
  13. printf("******* 扫雷小游戏 *********\n");
  14. printf("******* 1、play *********\n");
  15. printf("******* 0、exit *********\n");
  16. printf("*********************************\n");
  17. }
  18. //初始化数组
  19. void InitBoard(char board[ROWS][COLS], int rows, int cols, char ret)
  20. {
  21. int x = 0;
  22. int y = 0;
  23. for (x = 0; x < rows; x++)
  24. {
  25. for (y = 0; y < cols; y++)
  26. {
  27. board[x][y] = ret;
  28. }
  29. }
  30. }
  31. //打印棋盘
  32. void DisplayBoard(char board[ROWS][COLS], int row, int col)
  33. {
  34. int x = 0;
  35. int y = 0;
  36. printf("--------扫雷---------\n");
  37. for (x = 0; x <= row; x++)
  38. {
  39. printf(" %d", x);
  40. }
  41. printf("\n");
  42. for (x = 1; x <= row; x++)
  43. {
  44. printf(" %d", x);
  45. for (y = 1; y <= col; y++)
  46. {
  47. printf(" %c", board[x][y]);
  48. }
  49. printf("\n");
  50. }
  51. printf("---------------------\n");
  52. }
  53. //布置雷
  54. void Setmine(char board[ROWS][COLS], int row, int col)
  55. {
  56. int x = 0;
  57. int y = 0;
  58. int count = COUNT_EASY;
  59. while (count)
  60. {
  61. x = rand() % row + 1;
  62. y = rand() % col + 1;
  63. if (board[x][y] == '0')
  64. {
  65. board[x][y] = '1';
  66. count--;
  67. }
  68. }
  69. }
  70. //数周围有几个雷
  71. int GetMineCount(char mine[ROWS][COLS], int x, int y)
  72. {
  73. return (mine[x - 1][y - 1] +
  74. mine[x][y - 1] +
  75. mine[x + 1][y - 1] +
  76. mine[x + 1][y] +
  77. mine[x + 1][y + 1] +
  78. mine[x][y + 1] +
  79. mine[x - 1][y + 1] +
  80. mine[x - 1][y]) - (8 * '0');
  81. }
  82. //排查雷
  83. void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
  84. {
  85. int x = 0;
  86. int y = 0;
  87. int win = row * col - COUNT_EASY;
  88. while (win )
  89. {
  90. printf("请输入要排查的坐标->");
  91. scanf("%d %d", &x, &y);
  92. if (x >= 1 && x <= row && y >= 1 && y <= col)
  93. {
  94. if (mine[x][y] == '1')
  95. {
  96. printf("踩到雷啦!爆炸!\n");
  97. DisplayBoard(mine, row, col);
  98. break;
  99. }
  100. else if (show[x][y] != '*')
  101. {
  102. printf("排查过该坐标,请重新输入\n");
  103. }
  104. else if (mine[x][y] == '0')
  105. {
  106. int ret = 0;
  107. ret = GetMineCount(mine, x, y);
  108. show[x][y] = ret + '0';
  109. DisplayBoard(show, ROW, COL);
  110. win--;
  111. }
  112. }
  113. else
  114. {
  115. printf("输入坐标非法,请重新输入\n");
  116. }
  117. }
  118. if(win==0)
  119. printf("恭喜你,排雷成功! \n");
  120. }
  121. void game()
  122. {
  123. //为了方便,把两个数组定义成完全一样的
  124. char mine[ROWS][COLS] = { 0 };
  125. char show[ROWS][COLS] = { 0 };
  126. //初始化两个数组
  127. InitBoard(mine, ROWS, COLS, '0');
  128. InitBoard(show, ROWS, COLS, '*');
  129. //打印棋盘
  130. //DisplayBoard(mine, ROW, COL);
  131. //对应雷的数组不需要给玩家看
  132. DisplayBoard(show, ROW, COL);
  133. //布置雷
  134. Setmine(mine, ROW, COL);
  135. //DisplayBoard(mine, ROW, COL);
  136. //排查雷
  137. Findmine(mine, show, ROW, COL);
  138. }
  139. int main()
  140. {
  141. srand((unsigned int)time(NULL));
  142. int input = 0;
  143. do {
  144. menu();
  145. printf("请输入->");
  146. scanf("%d", &input);
  147. switch (input)
  148. {
  149. case 1:
  150. printf("开始游戏\n");
  151. game();
  152. break;
  153. case 0:
  154. printf("退出游戏\n");
  155. break;
  156. default:
  157. printf("输错了,请重新输入\n");
  158. break;
  159. }
  160. } while (input);
  161. return 0;
  162. }

大家也可以将其封装为多个文件看上去更简洁明了,我这里为了表达方便将其放在一个文件里。


以上就是  C语言基础:扫雷游戏的C语言实现(超详图解+源码)的全部内容啦,希望能对你有所帮助!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/921219
推荐阅读
相关标签
  

闽ICP备14008679号