当前位置:   article > 正文

【C语言/扫雷】手把手教你写一个扫雷小游戏,可展开_扫雷小程序

扫雷小程序

目录

一、制作一个菜单

1.菜单栏

 二、游戏函数的实现

1.雷盘的实现

2.布置雷

3.开始扫雷

1.整体逻辑

2.统计雷的数量

3.递归展开

 4.判断是否排雷成功

 三、代码的优化

四、总结

五、源代码


一、制作一个菜单

1.菜单栏

首先我们需要一个菜单来选择开始游戏或者退出游戏,do...while循环至少会运行一次符合我们对游戏程序的要求

  1. #include <stdio.h>
  2. void mean()
  3. {
  4. printf("************************\n");
  5. printf("***** 0.退出游戏 *****\n");
  6. printf("***** 1.开始游戏 *****\n");
  7. printf("************************\n");
  8. }
  9. void game()
  10. {
  11. }
  12. int main()
  13. {
  14. int n = 0;
  15. do
  16. {
  17. mean();
  18. scanf("%d", &n);
  19. switch (n)
  20. {
  21. case 0:
  22. break;
  23. case 1:
  24. game();
  25. break;
  26. default:
  27. printf("请选择正确的选项\n");
  28. break;
  29. }
  30. } while (n);
  31. }

测试我们的菜单逻辑没有问题 

 二、游戏函数的实现

1.雷盘的实现

 初阶扫雷的棋盘为9x9所以我们需要一个创建一个二维数组作为棋盘,考虑到我们需要在游戏未结束之前隐藏雷的位置和棋盘的内容,为了方便起见我们可以创建两个棋盘。一个用来展示,一个用来存放雷。

我们在选择一个位置后,如果不是雷则需要判断周围8格有几个雷,为了避免数组越界我们创建的存放雷的棋盘要比实际的宽两格,ROW和COL是我们创建的一个宏,值为9.

ROWS和COLS是(ROW+1)和(COL+1)

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

 数组创建之后我们需要将其初始化,考虑到需要,我们将展示的棋盘数组全部初始化为*

存放雷的棋盘全部初始化为0

为了方便后续代码的编写,我们将展示的棋盘也设置为11x11,不过在打印时只打印9x9

初始化完成之后将棋盘打印出来

  1. void game()
  2. {
  3. char show_board[ROWS][COLS];
  4. char memory_board[ROWS][COLS];
  5. init_show(show_board,ROW,COL);//初始化展示的棋盘
  6. init_memory(memory_board, ROWS, COLS);//初始化存放雷的棋盘
  7. printf_board(show_board, ROW, COL);
  8. printf_board(memory_board, ROW, COL);
  9. }

  1. void init_show(char board[][COL],int row,int col)
  2. {
  3. int i, j;
  4. for (i = 0; i < row; i++)
  5. {
  6. for (j = 0; j < col; j++)
  7. {
  8. board[i][j] = '*';
  9. }
  10. }
  11. }
  12. void init_memory(char board[][COLS], int row, int col)
  13. {
  14. int i, j;
  15. for (i = 0; i < row; i++)
  16. {
  17. for (j = 0; j < col; j++)
  18. {
  19. board[i][j] = '0';
  20. }
  21. }
  22. }
  23. void printf_board(char board[][COLS], int row, int col)
  24. {
  25. int i, j;
  26. for (i = 0; i < col; i++)
  27. {
  28. printf("%d ", i);
  29. }
  30. printf("\n");
  31. for (i = 1; i < row; i++)
  32. {
  33. printf("%d ", i);
  34. for (j = 1; j < col; j++)
  35. {
  36. printf("%c ", board[i][j]);
  37. }
  38. printf("\n");
  39. }
  40. }

 

 测试结果符合预期,其中存放雷的棋盘只是为了方便观察和编写程序才将其打印出来,程序完成之后将其删去。

2.布置雷

此时我们已经有了一个符合要求的棋盘,那么我们需要将雷布置到存放雷的棋盘中。

初阶扫雷有10个雷,所以我们需要将10个雷布置到我们的数组当中。

  1. void place_mine(char board[][COLS], int row, int col)
  2. {
  3. int i = 0;
  4. while (i<mined)//mined是我们定义的一个宏用来确定放置雷的数量
  5. {
  6. int x = rand() %row+1;
  7. int y = rand() %co+l;
  8. if (board[x][y] == '0')
  9. {
  10. board[x][y] = '1';
  11. i++;
  12. }
  13. }
  14. }

可以看到我们已经将10个雷分布到了雷盘中

3.开始扫雷

1.整体逻辑

首先我们需要输入一个坐标,然后在在输入之后首先判断是否是雷,如果是雷则游戏结束。

如果不是雷则需要将,一圈八格雷的总数展示出来。

  1. void saolei(char showboard[][COLS],char memoryboard[][COLS])
  2. {
  3. int x = 0,y=0;
  4. while (1)
  5. {
  6. printf("请输入坐标:\n");
  7. scanf(" %d%d", &x, &y);
  8. if (x <= ROW && x > 0&&y > 0 && y <= COL&& showboard[x][y] == '*')
  9. {
  10. if (memoryboard[x][y] == '1')
  11. {
  12. printf_board(memoryboard, ROW, COL);
  13. printf("boom*\n");
  14. printf("you die\n");
  15. break;
  16. }
  17. else
  18. {
  19. count(showboard, memoryboard, x, y);
  20. }
  21. if (showboard[x][y] == '0' && x > 0 && y > 0)
  22. ufold(showboard, memoryboard, x, y);
  23. printf_board(showboard, ROW, COL);
  24. int win=whether_win(showboard,ROW,COL);
  25. if (win)
  26. {
  27. printf("恭喜排雷成功\n");
  28. printf_board(showboard, ROW, COL);
  29. printf_board(memoryboard, ROW, COL);
  30. break;
  31. }
  32. }
  33. else
  34. printf("坐标不合法,请重新输入\n");
  35. }
  36. }

2.统计雷的数量

  1. void count(char showboard[][COLS],char memoryboard[][COLS], int x, int y)
  2. {
  3. int i = 0, j = 0;
  4. char sum = '0';
  5. for (i = x - 1; i <= x + 1; i++)
  6. {
  7. for (j = y - 1; j <= y + 1; j++)
  8. {
  9. if (memoryboard[i][j] == '1')
  10. sum++;
  11. }
  12. }
  13. showboard[x][y] = sum;
  14. }

3.递归展开

在扫雷中如果我们选择的位置周围没有雷,则会展开周围八格,然后展开的格子中如果存在周围没有雷的格子则会继续展开。

所以这里我们可以写一个递归,让它每次识别到没有雷的格子就继续展开。

注意添加限制条件避免数组越界,此处编写过程中条件如果不完善容易陷入死循环,如果在调试运行过程中出现栈溢出的错误,可以仔细检查这里看是否出现死循环。

  1. void ufold(char showboard[][COLS], char memoryboard[][COLS], int x, int y)
  2. {
  3. int i = 0, j = 0;
  4. int num = 0;
  5. for (i = x - 1; i <= x + 1; i++)
  6. {
  7. for (j = y - 1; j <= y + 1; j++)
  8. {
  9. if (i > 0 && i <= ROW && j > 0 && j <= COL && showboard[i][j] == '*')
  10. {
  11. count(showboard, memoryboard, i, j);
  12. if(showboard[i][j]=='0')
  13. ufold(showboard, memoryboard, i, j);
  14. }
  15. }
  16. }
  17. }

 测试递归展开逻辑没有问题

 4.判断是否排雷成功

  1. int whether_win(char showboard[][COLS], int row, int col)
  2. {
  3. int sum = 0;
  4. int i = 0, j = 0;
  5. for (i = 1; i <= row; i++)
  6. {
  7. for (j = 1; j <= col; j++)
  8. {
  9. if (showboard[i][j] == '*')
  10. sum++;
  11. if (sum > mined)
  12. return 0;
  13. }
  14. }
  15. return 1;
  16. }

在这里为了节省时间提高效率,我们可以将雷数量mine改为2进行测试。测试完毕没有问题。

#define mined 2//雷的数量

 三、代码的优化

1.删去      printf_board(memory_board, ROW, COL);这个是我们存放雷的棋盘,为了方便观察才打印出来的。

2.美化雷盘,美化到自己满意即可,此处不做过多演示

  1. void printf_board(char board[][COLS], int row, int col)
  2. {
  3. int i, j;
  4. printf(" ");
  5. for (i = 0; i <= col; i++)
  6. {
  7. printf("%d ", i);
  8. }
  9. printf("\n");
  10. for (i = 0; i <= col; i++)
  11. {
  12. printf("--");
  13. }
  14. printf("\n");
  15. for (i = 1; i <= row; i++)
  16. {
  17. printf("%d |", i);
  18. for (j = 1; j <= col; j++)
  19. {
  20. printf("%c ", board[i][j]);
  21. }
  22. printf("\n");
  23. }
  24. }

3.在合适位置添加清屏函数提升界面美观度

windows系统下可以使用system("cls"),头文件为stdlib.h

四、总结

    代码整体难度较低,所用到的知识非常基础,在编写时保证头脑清晰冷静可以较快完成。

五、源代码

头文件

  1. #define _CRT_SECURE_NO_WARNINGS 1
  2. #define ROW 9
  3. #define COL 9
  4. #define ROWS (ROW+2)
  5. #define COLS (COL+2)
  6. #define mined 10//雷的数量
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <time.h>
  10. void init_show(char board[][COLS], int row, int col);//初始化展示的棋盘
  11. void init_memory(char board[][COLS], int row, int col);//初始化存放雷的棋盘
  12. void printf_board(char board[][COLS], int row, int col);//打印棋盘
  13. void place_mine(char board[][COLS], int row, int col);//布置雷
  14. void saolei(char showboard[][COLS], char memoryboard[][COLS]);//扫雷
  15. void count(char showboard[][COLS], char memoryboard[][COLS], int x, int y);//计算雷的数量
  16. void ufold(char showboard[][COLS], char memoryboard[][COLS], int x, int y);//递归展开没有雷的格子
  17. int whether_win(char showboard[][COLS], int row, int col);//判断是否成功

test.c

  1. #include "game.h"
  2. void mean()
  3. {
  4. printf("************************\n");
  5. printf("***** 0.退出游戏 *****\n");
  6. printf("***** 1.开始游戏 *****\n");
  7. printf("************************\n");
  8. }
  9. void game()
  10. {
  11. char show_board[ROWS][COLS];
  12. char memory_board[ROWS][COLS];
  13. init_show(show_board,ROWS,COLS);
  14. init_memory(memory_board, ROWS, COLS);
  15. place_mine(memory_board, ROW, COL);
  16. printf_board(show_board, ROW, COL);
  17. saolei(show_board, memory_board);
  18. }
  19. int main()
  20. {
  21. srand((unsigned int)time(NULL));
  22. int n = 0;
  23. do
  24. {
  25. mean();
  26. scanf("%d", &n);
  27. switch (n)
  28. {
  29. case 0:
  30. break;
  31. case 1:
  32. game();
  33. break;
  34. default:
  35. printf("请选择正确的选项\n");
  36. break;
  37. }
  38. } while (n);
  39. }

game.c

  1. #include "game.h"
  2. void init_show(char board[][COLS],int row,int col)
  3. {
  4. int i, j;
  5. for (i = 0; i < row; i++)
  6. {
  7. for (j = 0; j < col; j++)
  8. {
  9. board[i][j] = '*';
  10. }
  11. }
  12. }
  13. void init_memory(char board[][COLS], int row, int col)
  14. {
  15. int i, j;
  16. for (i = 0; i < row; i++)
  17. {
  18. for (j = 0; j < col; j++)
  19. {
  20. board[i][j] = '0';
  21. }
  22. }
  23. }
  24. void printf_board(char board[][COLS], int row, int col)
  25. {
  26. int i, j;
  27. printf(" ");
  28. for (i = 1; i <= col; i++)
  29. {
  30. printf("%d ", i);
  31. }
  32. printf("\n");
  33. for (i = 0; i <= col; i++)
  34. {
  35. printf("--");
  36. }
  37. printf("\n");
  38. for (i = 1; i <= row; i++)
  39. {
  40. printf("%d |", i);
  41. for (j = 1; j <= col; j++)
  42. {
  43. printf("%c ", board[i][j]);
  44. }
  45. printf("\n");
  46. }
  47. }
  48. void place_mine(char board[][COLS], int row, int col)
  49. {
  50. int i = 0;
  51. while (i<mined)
  52. {
  53. int x = rand()%row+1;
  54. int y = rand()%col+1;
  55. if (board[x][y] == '0')
  56. {
  57. board[x][y] = '1';
  58. i++;
  59. }
  60. }
  61. }
  62. void ufold(char showboard[][COLS], char memoryboard[][COLS], int x, int y)
  63. {
  64. int i = 0, j = 0;
  65. int num = 0;
  66. for (i = x - 1; i <= x + 1; i++)
  67. {
  68. for (j = y - 1; j <= y + 1; j++)
  69. {
  70. if (i > 0 && i <= ROW && j > 0 && j <= COL && showboard[i][j] == '*')
  71. {
  72. count(showboard, memoryboard, i, j);
  73. if(showboard[i][j]=='0')
  74. ufold(showboard, memoryboard, i, j);
  75. }
  76. }
  77. }
  78. }
  79. void count(char showboard[][COLS],char memoryboard[][COLS], int x, int y)
  80. {
  81. int i = 0, j = 0;
  82. char sum = '0';
  83. for (i = x - 1; i <= x + 1; i++)
  84. {
  85. for (j = y - 1; j <= y + 1; j++)
  86. {
  87. if (memoryboard[i][j] == '1')
  88. sum++;
  89. }
  90. }
  91. showboard[x][y] = sum;
  92. }
  93. int whether_win(char showboard[][COLS], int row, int col)
  94. {
  95. int sum = 0;
  96. int i = 0, j = 0;
  97. for (i = 1; i <= row; i++)
  98. {
  99. for (j = 1; j <= col; j++)
  100. {
  101. if (showboard[i][j] == '*')
  102. sum++;
  103. if (sum > mined)
  104. return 0;
  105. }
  106. }
  107. return 1;
  108. }
  109. void saolei(char showboard[][COLS],char memoryboard[][COLS])
  110. {
  111. int x = 0,y=0;
  112. while (1)
  113. {
  114. printf("请输入坐标:\n");
  115. scanf(" %d%d", &x, &y);
  116. system("cls");
  117. if (x <= ROW && x > 0&&y > 0 && y <= COL&& showboard[x][y] == '*')
  118. {
  119. if (memoryboard[x][y] == '1')
  120. {
  121. printf_board(memoryboard, ROW, COL);
  122. printf_board(showboard, ROW, COL);
  123. printf("boom*\n");
  124. printf("you die\n");
  125. break;
  126. }
  127. else
  128. {
  129. count(showboard, memoryboard, x, y);
  130. }
  131. if (showboard[x][y] == '0' && x > 0 && y > 0)
  132. ufold(showboard, memoryboard, x, y);
  133. printf_board(showboard, ROW, COL);
  134. int win=whether_win(showboard,ROW,COL);
  135. if (win)
  136. {
  137. printf("恭喜排雷成功啦>>>>>>>>>>>\n");
  138. printf_board(showboard, ROW, COL);
  139. printf_board(memoryboard, ROW, COL);
  140. break;
  141. }
  142. }
  143. else
  144. printf("坐标不合法,请重新输入\n");
  145. }
  146. }

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号