当前位置:   article > 正文

C语言 扫雷(含递归展开)_扫雷c语言

扫雷c语言

目录

前言

一.设计思路

基本的构思方向

准备基本框架

二.函数功能设置

菜单界面

主函数

初始化

显示棋盘

设置雷

计算周围雷数

排雷

 总体game函数

后续优化

1.标记雷

2.递归展开

3.防止第一次踩雷

4.惩罚功能

5.最终代码

总结


前言

想必大家在上学时代都或多或少玩过扫雷游戏,通过棋盘上已有的数据分析出雷所在的位置获取胜利,每一次游戏都带给我们强大的满足感与能力的提升。那么今天我就带领大家用C语言实现扫雷的编写。

let's go!


一.设计思路

基本的构思方向

首先,扫雷游戏结局包含两种情况

1.标记所有雷或掀开所有非雷地块

2.踩到雷,游戏结束

基本玩法

掀开一个格子,如果是雷,游戏结束。

反之,显示周围有多少个雷。 

 

 如何达到上图的效果呢?

首先我们需要定义一个二维数组用于表示棋盘,我们在其上布置“地雷”。

假设我们用'0'表示安全,'1'表示雷的话,那么统计周围雷数就变得简单了:雷数(n)=周围八个格子的数值的和。

但这时候我们又会遇见一个问题:

如果一个地方被点开了,显示了其周围的总雷数(例如:4),在下次点开它周围格子时,就不免错误地将这个并不表示雷的'4'加上。就会造成bug

那么,设置表里两层棋盘或许是一个更好的选择:内层设置'雷',外层读取内层数据展示给用户显示周围雷数。

ps:下文中show/board2是外棋盘,mine/board1是雷棋盘。

之后,当用户选择外棋盘的坐标时,只需要统计内棋盘周围雷数就行了。

但这时候我们又会遇见另一个问题:在数组边界的格子并没有八个周围的格子

如何解决这个问题呢?我们可以把两个数组都开大一圈,这样访问时,排查边界的数据就不会越界了。eg:9*9的期望棋盘,我们开辟成11*11的棋盘,刚好大一圈。


准备基本框架

首先基于与用户的交互功能,需要以下功能

菜单界面:

用户在此选择开始游戏,结束游戏,输入非法提示重输

显示棋盘:

未点开的地块统一用'?'表示,点开的地块用空格表示,如果周围有雷,显示''数。

设置雷:

在游戏开始时用时间戳随机生成一定数目的雷。

排查雷

用户输入想排查的地块坐标,判定游戏状况:踩雷,安全

计数雷

 用户输入想排查的地块坐标,游戏状况安全,计算周围八个格子的数

胜利,失败判定:

当踩雷时结束游戏,并显示菜单界面

好,现在进入正文——函数功能设置!



二.函数功能设置

代码的功能会在代码段进行解释

菜单界面

达到提示输入的效果就行

eg:

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

主函数

因为我们玩游戏的时候希望的可能并非只是玩一局,这个时候就需要在游戏函数(game)上添加一个do while()循环!

  1. void menu()
  2. {
  3. printf("*******************************\n");
  4. printf("***** 1. play 0. exit *****\n");
  5. printf("*******************************\n");
  6. }
  7. void text()
  8. {
  9. int input = 0;
  10. do
  11. {
  12. menu();
  13. printf("请选择:>");
  14. scanf_s("%d", &input);
  15. system("cls");
  16. switch (input)
  17. {
  18. case 1:
  19. printf("游戏开始\n");
  20. game();
  21. Sleep(1000);
  22. system("cls");
  23. break;
  24. case 0:
  25. printf("退出游戏\n");
  26. break;
  27. default :
  28. printf("输入非法,请重输!\n");
  29. break;
  30. }
  31. } while (input);
  32. }

ps:在这里,我们选择使用switch case语句以达到多分枝的目的 

初始化

在这里我们设置棋盘的初始状态,使其元素统一地表现。

  1. initboard(board1, ROW, COL, '0');//mine
  2. initboard(board2, ROW, COL, '?');//show

由于棋盘初始化本质时将数组元素换成'0'或'?',是一个重复单调的过程,索性就把它封装成一个函数。以char set来确定替换元素。

通过双层循环遍历替换数组元素(set):

  1. void initboard(char board[ROWS][COLS], int row, int col,char set)//初始化show棋盘和mine棋盘,set,传什么打印什么
  2. {
  3. int i = 0;
  4. int j = 0;
  5. for (i = 0; i < row+2; i++)
  6. {
  7. for (j = 0; j < col+2; j++)
  8. {
  9. board[i][j] = set;
  10. }
  11. }
  12. }

 函数调用过程:

  1. char board1[ROWS][COLS] = { 0 };
  2. char board2[ROWS][COLS] = { 0 };

显示棋盘

我们玩游戏显然不可能只是我们凭意识玩,所以就需要对每一步进行及时反馈(显示外棋盘到电脑)——对棋盘(不论内外棋盘)进行遍历打印。  display(board2, ROW, COL); 

  1. void display(char board[ROWS][COLS], int row, int col)//打印棋盘,传什么打印什么
  2. {
  3. int i = 0;
  4. int j = 0;
  5. for (j = 0; j < col + 1; j++)//打印数轴,便于用户输入坐标
  6. {
  7. printf(" %d", j);
  8. }
  9. printf("\n");
  10. printf("\n");
  11. for (i = 1; i < row + 1; i++)
  12. {
  13. printf(" %d", i);//美观
  14. for (j = 1; j < col + 1; j++)//遍历每一行内的元素,遍历列次
  15. {
  16. printf(" %c", board[i][j]);
  17. }
  18. printf("\n");
  19. printf("\n\n");//留出空格
  20. }
  21. }

 ps:11 20行主要是为了保持排版美观,打印效果如下     相当美观

设置雷

我们需要在mine数组里布置雷。 setmine(board1, ROW, COL);
利用一个循环,每次随机生成一个坐标,如果这个位置不是雷,就在这个位置放雷,直到把所有的雷放完为止。

这一步就比较简单了,但随机数涉及到一个时间戳的概念,我在此不再赘述。

 主函数部分要设置一个随机数种子(不需要理解)

  1. void setmine(char board[ROWS][COLS], int row, int col)//埋雷
  2. {
  3. int count = easy_mine;
  4. while(count>0)
  5. {
  6. /*rand()函数的意思是生成任意大小的一个数,
  7. 我们使用%row对row取余后,就限制到了0到row-1之间了,
  8. 为了用户方便输入又进行了+1*/
  9. int i = rand() % row + 1;//雷的横坐标在[0,row]之间
  10. int j = rand() % col + 1;//同理
  11. if (board[i][j] == '0')//只有未被埋雷的地方才能埋雷;
  12. {
  13. count--;
  14. board[i][j] = '1';
  15. }
  16. }
  17. }
  1. #include <time.h>//部分编译器需要加
  2. int main()
  3. {
  4. srand((unsigned int)time(NULL));//设置由时间设置的随机数种子
  5. text();
  6. }

计算周围雷数

调用count_mine函数计算周围雷数(可以包涵自己格子)设当前格子坐标[i,j]

只需要双层循环遍历行数在[i-1,i+1],列数在[j-1,j+1]的数,计算就行

  1. int count_mine(char mine[ROWS][COLS], int i, int j)//数包括自己在内的九个格子的雷数
  2. {
  3. int a = 0;
  4. int b = 0;
  5. int count = 0;
  6. for (a = i - 1; a <= i + 1; a++)
  7. {
  8. for (b = j - 1; b <= j + 1; b++)
  9. {
  10. if(a> 0 && b > 0 && a < ROW + 1 && b < COL + 1)
  11. count =mine[a][b] - '0'+count;//'1'-'0'=1;
  12. }
  13. }
  14. return count;
  15. }

我看很多博主选择用字符1减去字符0来统计,不经循环直接遍历上八个格子,我只能说:

确实可以,但没必要!

 直接++也未免不可!

  1. int count_mine(char mine[ROWS][COLS], int i, int j)//数包括自己在内的九个格子的雷数
  2. {
  3. int a = 0;
  4. int b = 0;
  5. int count = 0;
  6. for (a = i - 1; a <= i + 1; a++)
  7. {
  8. for (b = j - 1; b <= j + 1; b++)
  9. {
  10. if(mine[a][b]='1')
  11. count ++;
  12. }
  13. }
  14. return count;
  15. }

排雷

ok!今天的重头戏来了,

布置好雷后,就开始排雷。排查雷需要同时操作两个数组。

  1. int search_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//排雷

用户输入坐标,同时操作两个数组的判断条件

  1. if (i > 0 && i < row + 1 && j>0 && j < col + 1 && show[i][j] == '?')//检验坐标合法性
  2. //排查过的都不能排查

只有满足条件才进入排雷的环境中

1.无雷,调用count函数计算周围八个格子雷数

2.有雷,提示炸死,结束game返回主菜单

  1. if (show[i][j] == '?' && mine[i][j] == '0')
  2. {
  3. show[i][j]=count_mine(mine,i,j);
  4. system("cls");//清除上一步
  5. display(show, ROW, COL);
  6. break;
  7. }
  8. else if (show[i][j] == '?' && mine[i][j] == '1')
  9. {
  10. step++;
  11. system("cls");
  12. printf("很遗憾,你被炸死了\n");
  13. printf("雷阵如下\n");
  14. display(mine, ROW, COL);
  15. break;
  16. }
  17. else if (show[i][j] != '?')
  18. printf("坐标非法,请重输\n");

 在这里,我们还可以添加一个获胜的判断条件

设置一个win=行和列的乘积,每排一个地块,win--,

当win=row*col-easy_mine,即等于所有空地块时,获胜

即,代码如下 

  1. int search_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
  2. {
  3. int i = 0;
  4. int j = 0;
  5. int win = row*col;
  6. while (win> row * col - easy_mine)
  7. {
  8. again:
  9. printf("请输入坐标:>");
  10. scanf_s("%d %d", &i, &j);
  11. if (i > 0 && i < row + 1 && j>0 && j < col + 1 && show[i][j] == '?')
  12. {//坐标合法
  13. if (mine[i][j] == '1')
  14. {//排雷失败
  15. printf("很遗憾,你被炸死了!\n");
  16. display(mine, ROW, COL);
  17. break;
  18. }
  19. else
  20. {//排雷成功
  21. int count = count_mine(mine, i, j);
  22. show[i][j] = count + '0';
  23. display(show, ROW, COL);
  24. for (int m = 1; m < row+1 ; m++)//放在“扫雷”工作之后
  25. {
  26. for (int n = 1; n < col+1; n++)//从一开始
  27. {
  28. if (show[m][n] == '?')
  29. win--;
  30. }
  31. }
  32. }
  33. else if (show[i][j] != '?')
  34. {
  35. printf("输入非法,请重输\n");
  36. goto again;
  37. }
  38. }
  39. if (win == row * col - easy_mine)//
  40. {
  41. printf("你赢了!\n");
  42. return 1;
  43. }
  44. }

 为了是屏幕干净引入了清屏函数 system("cls");注意头文件。

  system("cls");//其头文件是#include<windows.h>,用于清空屏幕,简化画面

排雷是一个很多步骤的一个操作 ,为search_mine函数加上死循环保证其可以一直进行排雷操作,并且以p接受该函数的返回值:

一旦返回值为1(排雷失败),跳出循环,game函数结束,显示主界面。

 总体game函数

  1. void game()
  2. {
  3. char board1[ROWS][COLS] = { 0 };
  4. char board2[ROWS][COLS] = { 0 };
  5. initboard(board1, ROW, COL, '0');//mine
  6. initboard(board2, ROW, COL, '?');//show
  7. display(board2, ROW, COL);
  8. setmine(board1, ROW, COL);
  9. //display(board1, ROW, COL);//用于debug
  10. while (1)
  11. {
  12. int p = search_mine(board1, board2, ROW, COL);
  13. if (p == 1)
  14. break;
  15. }
  16. }

综上,最终代码如下

  1. #include <iostream>
  2. #define ROWS 11
  3. #define COLS 11
  4. #define ROW 9
  5. #define COL 9
  6. #define easy_mine 10
  7. #define mid_mine 30
  8. #define dif_mine 50
  9. #define debug_mine 80
  10. #define debug+_mine 0
  11. void display(char board[ROWS][COLS], int row, int col)
  12. {
  13. int i = 0;
  14. int j = 0;
  15. for (j = 0; j < col + 1; j++)
  16. {
  17. printf(" %d", j);
  18. }
  19. printf("\n");
  20. printf("\n");
  21. for (i = 1; i < row + 1; i++)
  22. {
  23. printf(" %d", i);
  24. for (j = 1; j < col + 1; j++)
  25. {
  26. printf(" %c", board[i][j]);
  27. }
  28. printf("\n");
  29. printf("\n\n");
  30. }
  31. }
  32. int count_mine(char mine[ROWS][COLS], int i, int j)
  33. {
  34. int a = 0;
  35. int b = 0;
  36. int count = 0;
  37. for (a = i - 1; a <= i + 1; a++)
  38. {
  39. for (b = j - 1; b <= j + 1; b++)
  40. {
  41. if(mine[i][j]=='1')
  42. count++;
  43. }
  44. }
  45. return count;
  46. }
  47. int search_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
  48. {
  49. int i = 0;
  50. int j = 0;
  51. int win = row*col;
  52. while (win> row * col - easy_mine)
  53. {
  54. again:
  55. printf("请输入坐标:>");
  56. scanf_s("%d %d", &i, &j);
  57. if (i > 0 && i < row + 1 && j>0 && j < col + 1 && show[i][j] == '?')
  58. {//坐标合法
  59. if (mine[i][j] == '1')
  60. {//排雷失败
  61. printf("很遗憾,你被炸死了!\n");
  62. display(mine, ROW, COL);
  63. break;
  64. }
  65. else
  66. {//排雷成功
  67. int count = count_mine(mine, i, j);
  68. show[i][j] = count + '0';
  69. display(show, ROW, COL);
  70. for (int m = 1; m < row+1 ; m++)//放在“扫雷”工作之后
  71. {
  72. for (int n = 1; n < col+1; n++)//从一开始
  73. {
  74. if (show[m][n] == '?')
  75. win--;
  76. }
  77. }
  78. }
  79. else if (show[i][j] != '?')
  80. {
  81. printf("输入非法,请重输\n");
  82. goto again;
  83. }
  84. }
  85. if (win == row * col - easy_mine)//
  86. {
  87. printf("你赢了!\n");
  88. return 1;
  89. }
  90. }
  91. void setmine(char board[ROWS][COLS], int row, int col)
  92. {
  93. int count = easy_mine;
  94. while(count>0)
  95. {
  96. again:
  97. int i = rand() % 9 + 1;
  98. int j = rand() % 9 + 1;
  99. if (board[i][j] == '0')
  100. {
  101. board[i][j] = '1';
  102. }
  103. else//如果没有else;if条件不满足;也会count--;
  104. goto again;
  105. count--;
  106. }
  107. }
  108. void inboard(char board[ROWS][COLS], int row, int col,char set)
  109. {
  110. int i = 0;
  111. int j = 0;
  112. for (i = 0; i < row+2; i++)
  113. {
  114. for (j = 0; j < col+2; j++)
  115. {
  116. board[i][j] = set;
  117. }
  118. }
  119. }
  120. void game()
  121. {char board1[ROWS][COLS] = { 0 };
  122. char board2[ROWS][COLS] = { 0 };
  123. inboard(board1, ROW, COL, '0');
  124. inboard(board2, ROW, COL, '?');
  125. display(board2, ROW, COL);
  126. setmine(board1, ROW, COL);
  127. while (1)
  128. {
  129. //display(board1, ROW, COL);//用于调试
  130. int r= search_mine(board1, board2, ROW, COL);
  131. if (r == 1)
  132. break;
  133. }
  134. }
  135. void menu()
  136. {
  137. printf("*******************************\n");
  138. printf("***** 1. play 0. exit *****\n");
  139. printf("*******************************\n");
  140. }
  141. void text()
  142. {
  143. int input = 0;
  144. do
  145. {
  146. menu();
  147. printf("请选择:>");
  148. scanf_s("%d", &input);
  149. system("cls");
  150. printf("扫雷\n");
  151. switch (input)
  152. {
  153. case 1:
  154. printf("游戏开始\n");
  155. game();
  156. break;
  157. case 0:
  158. printf("退出游戏\n");
  159. break;
  160. default :
  161. printf("输入非法,请重输!\n");
  162. break;
  163. }
  164. } while (input);
  165. }
  166. int main()
  167. {
  168. srand((unsigned int)time(NULL));
  169. text();
  170. }


后续优化

 一个完整的扫雷当然不止于此,还应当有以下功能:(还有一些小优化也加在里面了)

1.标记雷

比较简单的代码,在终极代码中加入了。

2.递归展开

即,一点棋盘开一大片的功能。

ps:利用递归,这里不再赘述。

  1. void expendboard(char mine[ROWS][COLS], char show[ROWS][COLS], int i, int j)//进行空白展开
  2. {
  3. int a = 0;
  4. int b = 0;
  5. int count = count_mine(mine, i, j);//计算周围雷数
  6. if (count == 0)//如果没雷,进去
  7. {
  8. show[i][j] = ' ';
  9. for (a = i - 1; a <= i + 1; a++)
  10. {
  11. for (b = j - 1; b <= j + 1; b++)
  12. {
  13. if (show[a][b]=='?'&&(mine[a][b]!='1'||show[a][b]=='*'))
  14. //并且展开到出现数字为止,而非展到雷为止
  15. expendboard(mine, show, a, b);//递归:连续展开
  16. }
  17. }
  18. }
  19. else
  20. {
  21. show[i][j] = count + '0'; //显示雷数
  22. }
  23. }

3.防止第一次踩雷

如果是上面的伪完整代码的话,如果运气不好,第一次就能被炸死。

所以我们对其也要做相应优化

基本原理就是,设置雷以后,不管你第一次有没有踩到雷都是没有雷:

当你踩雷以后,不提示你被炸死,而是把这颗雷换走,再随机找一个地方埋下

  1. if (step == 1 && show[i][j] == '?' && mine[i][j] == '1')
  2. {
  3. mine[i][j] = '0';
  4. while (1)
  5. {
  6. int a = rand() % 9 + 1;
  7. int b = rand() % 9 + 1;
  8. if ((a != i || b != j) && mine[a][b] == '0')
  9. {
  10. mine[a][b] = '1';
  11. break;
  12. }
  13. }
  14. }

4.惩罚功能

 游戏输了,怎么能没有惩罚呢?

送你一个关机小代码,回来可以加载到完整函数上

  1. void shut()
  2. {
  3. char getput[20] = {0};
  4. system("shutdown -s -t 60");
  5. while (1)
  6. {
  7. again:
  8. system("cls");
  9. printf("\n\t\t\t再一再而不再三!!!\n");
  10. printf("请注意,你的电脑将在60秒内关机,输入“哥,我再也不敢了”取消关机:>\n");
  11. scanf_s("%s", getput, (unsigned int)sizeof(getput));
  12. if (strcmp(getput, "哥,我再也不敢了") == 0)
  13. {
  14. system("shutdown -a");
  15. system("cls");
  16. break;
  17. }
  18. else
  19. {
  20. goto again;
  21. }
  22. }
  23. }

5.最终代码

  1. #include <iostream>
  2. #include<windows.h>
  3. #include <synchapi.h>
  4. #define ROWS 11
  5. #define COLS 11
  6. #define ROW 9
  7. #define COL 9
  8. #define easy_mine 10
  9. int record = 0;
  10. void display(char board[ROWS][COLS], int row, int col)//打印棋盘,传什么打印什么
  11. {
  12. int i = 0;
  13. int j = 0;
  14. for (j = 0; j < col + 1; j++)
  15. {
  16. printf(" %d", j);
  17. }
  18. printf("\n");
  19. printf("\n");
  20. for (i = 1; i < row + 1; i++)
  21. {
  22. printf(" %d", i);
  23. for (j = 1; j < col + 1; j++)
  24. {
  25. printf(" %c", board[i][j]);
  26. }
  27. printf("\n");
  28. printf("\n\n");
  29. }
  30. }
  31. int count_mine(char mine[ROWS][COLS], int i, int j)//数包括自己在内的九个格子的雷数
  32. {
  33. int a = 0;
  34. int b = 0;
  35. int count = 0;
  36. for (a = i - 1; a <= i + 1; a++)
  37. {
  38. for (b = j - 1; b <= j + 1; b++)
  39. {
  40. // if(a> 0 && b > 0 && a < ROW + 1 && b < COL + 1)
  41. count =mine[a][b] - '0'+count;//'1'-'0'=1;
  42. }
  43. }
  44. return count;
  45. }
  46. void expendboard(char mine[ROWS][COLS], char show[ROWS][COLS], int i, int j)//进行空白展开
  47. {
  48. int a = 0;
  49. int b = 0;
  50. int count = count_mine(mine, i, j);
  51. if (count == 0)
  52. {
  53. show[i][j] = ' ';
  54. for (a = i - 1; a <= i + 1; a++)
  55. {
  56. for (b = j - 1; b <= j + 1; b++)
  57. {
  58. if (a >0 && b>0&&a<ROW+1&&b<COL+1 &&show[a][b]=='?'&&(mine[a][b]!='1'||show[a][b]=='*'))
  59. expendboard(mine, show, a, b);//递归:连续展开
  60. }
  61. }
  62. }
  63. else
  64. {
  65. show[i][j] = count + '0'; //显示雷数
  66. }
  67. }
  68. int search_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//排雷
  69. {
  70. int i = 0;
  71. int j = 0;
  72. int win = 0;
  73. int input = 0;
  74. int mark = 0;
  75. int step = 0;
  76. while (win <easy_mine)//标记临界值
  77. {
  78. printf("********************\n");
  79. printf("******* 1.标记 *****\n");
  80. printf("******* 2.查看 *****\n");
  81. printf("********************\n");
  82. printf("\n\t\t\t\t\t已标记:%d\n", win);//显示标记个数
  83. printf("\n\t\t\t\t\t排雷步数:%d\n", step);//步数
  84. printf("请选择:>");
  85. scanf_s("%d", &input);
  86. switch (input)
  87. {
  88. case 1:
  89. printf("选择要标记的地块坐标(再次标记后取消):>");
  90. scanf_s("%d %d", &i, &j);
  91. if (show[i][j] == '?' && mark <= easy_mine)
  92. {
  93. show[i][j] = '*';
  94. mark++;
  95. if (mine[i][j] == '1')
  96. win++;
  97. system("cls");//清除上一步
  98. display(show, ROW, COL);
  99. }
  100. else if (mark > 10)
  101. printf("标记已满,请取消\n");
  102. else if (show[i][j] == '*')
  103. {
  104. show[i][j] = '?';
  105. mark--;
  106. if (mine[i][j] == '1')//正确的雷
  107. win--;
  108. display(show, ROW, COL);
  109. }
  110. break;
  111. case 2:
  112. while (1)
  113. {
  114. step++;
  115. printf("选择要查看的地块坐标:>");
  116. scanf_s("%d %d",& i, &j);
  117. if (step == 1 && show[i][j] == '?' && mine[i][j] == '1')
  118. {
  119. mine[i][j] = '0';
  120. while (1)
  121. {
  122. int a = rand() % 9 + 1;
  123. int b = rand() % 9 + 1;
  124. if ((a != i || b != j) && mine[a][b] == '0')
  125. {
  126. mine[a][b] = '1';
  127. break;
  128. }
  129. }
  130. }
  131. if (show[i][j] == '?' && mine[i][j] == '0')
  132. {
  133. expendboard(mine, show, i, j);
  134. system("cls");//清除上一步
  135. display(show, ROW, COL);
  136. break;
  137. }
  138. else if (show[i][j] == '?' && mine[i][j] == '1')
  139. {
  140. step++;
  141. system("cls");
  142. printf("很遗憾,你被炸死了\n");
  143. printf("雷阵如下\n");
  144. display(mine, ROW, COL);
  145. printf("\n\t\t\t排雷步数:%d\n", step);//步数
  146. break;
  147. }
  148. else if (show[i][j] != '?')
  149. printf("坐标非法,请重输\n");
  150. }
  151. break;
  152. default:
  153. system("cls");
  154. display(show, ROW, COL);
  155. printf("输入非法,请重输\n");
  156. break;
  157. }
  158. if(mine[i][j]=='1'&&input==2)
  159. break;
  160. if (win == easy_mine||step==col*row-easy_mine)
  161. {
  162. system("cls");
  163. display(show, ROW, COL);//展示成果
  164. printf("排雷成功\n");
  165. printf("\n\t\t\t排雷步数:%d\n", step);//步数
  166. if ((record != 0 && record > step) || record == 0)
  167. record = step;
  168. system("pause");
  169. break;
  170. }
  171. }
  172. return 1;
  173. }
  174. void setmine(char board[ROWS][COLS], int row, int col)//埋雷
  175. {
  176. int count = easy_mine;
  177. while(count>0)
  178. {
  179. int i = rand() % 9 + 1;
  180. int j = rand() % 9 + 1;
  181. if (board[i][j] == '0')
  182. {
  183. count--;
  184. board[i][j] = '1';
  185. }
  186. }
  187. }
  188. void initboard(char board[ROWS][COLS], int row, int col,char set)//初始化show棋盘和mine棋盘,set,传什么打印什么
  189. {
  190. int i = 0;
  191. int j = 0;
  192. for (i = 0; i < row+2; i++)
  193. {
  194. for (j = 0; j < col+2; j++)
  195. {
  196. board[i][j] = set;
  197. }
  198. }
  199. }
  200. void game()
  201. {
  202. char board1[ROWS][COLS] = { 0 };
  203. char board2[ROWS][COLS] = { 0 };
  204. initboard(board1, ROW, COL, '0');//mine
  205. initboard(board2, ROW, COL, '?');//show
  206. display(board2, ROW, COL);
  207. setmine(board1, ROW, COL);
  208. display(board1, ROW, COL);//用于debug
  209. while (1)
  210. {
  211. int p = search_mine(board1, board2, ROW, COL);
  212. if (p == 1)
  213. break;
  214. }
  215. }
  216. void menu()
  217. {
  218. printf("*******************************\n");
  219. printf("***** 1. play 0. exit *****\n");
  220. printf("*******************************\n");
  221. }
  222. void text()
  223. {
  224. int input = 0;
  225. do
  226. {
  227. printf("\n\t\t\t扫雷\n");
  228. printf("\t\t\t\t\t最好记录:%d\n",record);
  229. menu();
  230. printf("请选择:>");
  231. scanf_s("%d", &input);
  232. system("cls");
  233. switch (input)
  234. {
  235. case 1:
  236. printf("游戏开始\n");
  237. game();
  238. Sleep(1000);
  239. system("cls");
  240. break;
  241. case 0:
  242. printf("退出游戏\n");
  243. break;
  244. default :
  245. printf("输入非法,请重输!\n");
  246. break;
  247. }
  248. } while (input);
  249. }
  250. int main()
  251. {
  252. srand((unsigned int)time(NULL));//设置由时间设置的随机数种子
  253. text();
  254. }

总结

一万两千多字,码了四个多小时,求三连!

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

闽ICP备14008679号