当前位置:   article > 正文

C语言:扫雷游戏简单实现

C语言:扫雷游戏简单实现

目录

定义的一些变量

设计思路

为什么设计两个数组棋盘?

为什么游戏是9*9但设计数组要设计11*11?

初始化函数

为什么要把雷的棋盘初始化为0?

打印函数

布置雷

排除雷

解释为什么先前初始化记数字棋盘时选择0和1:

可以存在的优化

递归函数实现展开

借助图形库可视化能力更强

全部源码

定义的一些变量

为了代码的可读性和可操作性,开始前要定义一些值,后续有讲解:

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

设计思路

我们要创建两个字符串二维数组,一个用来存储雷的位置,一个用来给玩家提示信息的位置,玩家输入一个坐标,如果这个坐标是雷,就提示玩家被炸了,如果这个坐标不是雷,则提示玩家周围雷的数量,供玩家进行排雷。

为什么设计两个数组棋盘?

如果设计一个棋盘,则排雷和提示用户雷容易被干扰,代码可读性不强,而假设选择两个数组,把存储雷和排雷分开放,就可以在完成项目的同时还能使得代码可读性增强。

为什么游戏是9*9但设计数组要设计11*11?

在统计数量时,我们统计的是以该点为中心周围八个点的雷的个数,如果数组设置为9*9,那么在统计周围雷的个数时会导致越界访问,产生不必要的麻烦,因此在设计时选择11*11可以避免这样的问题。


初始化函数

棋盘被创建好了,那么就该进行初始化了,初始化后的内容就是要让用户看到的内容,在本实验的思路中,我们选择的是让用户看到的棋盘被*覆盖,但用来存放的棋盘也需要被初始化,于是初始化函数中可以加入新的参数。

为什么要把雷的棋盘初始化为0?

便于统计个数,后续的代码实现中会发现这样设置的优越性。

函数的实现:

  1. void Initboard(char board[][COLS], int rows, int cols, char c)
  2. {
  3. for (int i = 0; i < rows; i++)
  4. {
  5. for (int j = 0; j < cols; j++)
  6. board[i][j] = c;
  7. }
  8. }

打印函数

棋盘被设置和初始化后,就可以进行打印棋盘的函数实现了,只需要打印出数组的内容即可,要注意的是为了可读性,要打印出行和列对应的数字,代码实现如下:

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

布置雷

开头定义中我们定义了雷的个数,那么在实现函数时,基本思路是运用while循环,如果布置成功了就让雷的个数减一,直到雷的个数为0,此时判断结果为假,则此时就跳出循环,在进行判断时增加一些限制条件,判断坐标合法性等,综合考量就能得出下面的代码实现原理:

  1. void Setmine(char mineboard[][COLS], int row, int col)
  2. {
  3. int num = Set;
  4. while (num)
  5. {
  6. int x = rand() % row + 1;
  7. int y = rand() % col + 1;
  8. if (mineboard[x][y] == '0')
  9. {
  10. mineboard[x][y] = '1';
  11. num--;
  12. }
  13. }
  14. }

排除雷

来看实现的基本思路,玩家输入坐标,如果恰好是雷的位置那么玩家就被淘汰出局,如果不是雷的位置就显示周围雷的个数。

解释为什么先前初始化记数字棋盘时选择0和1:

在统计雷的个数的时候,统计的是周围八个格子的数据,如果先前我们选择的是#等作为雷的标记,那么在统计雷的时候就非常麻烦,但如果选择的是0和1,只需要把这些数据加起来最后减去一个'0'即可,这样就能把char类型的数据转换成int类型的数据,再返回到函数中即可。

那么具体的实现为:

  1. int Count(char board[][COLS], int x, int y)
  2. {
  3. return (board[x - 1][y] + board[x - 1][y - 1] + board[x - 1][y + 1] + board[x][y - 1] +
  4. board[x][y + 1] + board[x + 1][y] + board[x + 1][y - 1] + board[x + 1][y + 1]- 8*'0');
  5. }
  6. void FindSets(char mineboard[][COLS], char showboard[][COLS], int row, int col)
  7. {
  8. int x=0, y=0;
  9. int nums = row * col - Set;
  10. while (nums)
  11. {
  12. printf("请输入坐标:-->");
  13. scanf("%d %d", &x, &y);
  14. if (x >= 1 && x <= 9 && y >= 1 && y <= 9)
  15. {
  16. if (mineboard[x][y] == '1')
  17. {
  18. printf("被炸死了\n");
  19. break;
  20. }
  21. else
  22. {
  23. int ret = Count(mineboard, x, y);
  24. showboard[x][y] = ret + '0';
  25. Displayboard(showboard, ROW, COL);
  26. nums--;
  27. }
  28. }
  29. else
  30. {
  31. printf("坐标不合法,重新输入\n");
  32. }
  33. }
  34. if (nums == 0)
  35. {
  36. printf("扫雷成功,游戏结束\n");
  37. }
  38. }

可以存在的优化

递归函数实现展开

在实际的游戏过程中,在玩家点击一块没有雷的方格时,会将周围的部分都展开,而本文写的这个代码游戏不能达成这个效果,这里可以进行一定程度的优化,可以使用递归函数进行每个九宫格的展开。

借助图形库可视化能力更强

在实际游戏中是用了图形库的,这里只是一个简单的游戏实现,不包括图形库,图形库也可以作为代码的优化。

全部源码

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>
  4. #define ROW 9
  5. #define COL 9
  6. #define ROWS ROW+2
  7. #define COLS COL+2
  8. #define Set 10
  9. void Initboard(char board[][COLS], int rows, int cols, char c)
  10. {
  11. for (int i = 0; i < rows; i++)
  12. {
  13. for (int j = 0; j < cols; j++)
  14. board[i][j] = c;
  15. }
  16. }
  17. void Displayboard(char board[][COLS], int row, int col)
  18. {
  19. for (int i = 0; i <= row; i++)
  20. {
  21. if (i == 0)
  22. printf("%d|",i);
  23. else
  24. printf("%d ", i);
  25. }
  26. printf("\n");
  27. for (int i = 0; i < row; i++)
  28. {
  29. printf("--");
  30. }
  31. printf("\n");
  32. for (int i = 1; i <= row; i++)
  33. {
  34. printf("%d|", i);
  35. for (int j = 1; j <= col; j++)
  36. {
  37. printf("%c ", board[i][j]);
  38. }
  39. printf("\n");
  40. }
  41. printf("\n");
  42. }
  43. void Setmine(char mineboard[][COLS], int row, int col)
  44. {
  45. int num = Set;
  46. while (num)
  47. {
  48. int x = rand() % row + 1;
  49. int y = rand() % col + 1;
  50. if (mineboard[x][y] == '0')
  51. {
  52. mineboard[x][y] = '1';
  53. num--;
  54. }
  55. }
  56. }
  57. int Count(char board[][COLS], int x, int y)
  58. {
  59. return (board[x - 1][y] + board[x - 1][y - 1] + board[x - 1][y + 1] + board[x][y - 1] +
  60. board[x][y + 1] + board[x + 1][y] + board[x + 1][y - 1] + board[x + 1][y + 1]- 8*'0');
  61. }
  62. void FindSets(char mineboard[][COLS], char showboard[][COLS], int row, int col)
  63. {
  64. int x=0, y=0;
  65. int nums = row * col - Set;
  66. while (nums)
  67. {
  68. printf("请输入坐标:-->");
  69. scanf("%d %d", &x, &y);
  70. if (x >= 1 && x <= 9 && y >= 1 && y <= 9)
  71. {
  72. if (mineboard[x][y] == '1')
  73. {
  74. printf("被炸死了\n");
  75. break;
  76. }
  77. else
  78. {
  79. int ret = Count(mineboard, x, y);
  80. showboard[x][y] = ret + '0';
  81. Displayboard(showboard, ROW, COL);
  82. nums--;
  83. }
  84. }
  85. else
  86. {
  87. printf("坐标不合法,重新输入\n");
  88. }
  89. }
  90. if (nums == 0)
  91. {
  92. printf("扫雷成功,游戏结束\n");
  93. }
  94. }
  95. void menu()
  96. {
  97. printf("*****************************\n");
  98. printf("********* 1.game **********\n");
  99. printf("********* 0.exit **********\n");
  100. printf("*****************************\n");
  101. }
  102. void game()
  103. {
  104. srand((unsigned int)time(NULL));
  105. char mineboard[ROWS][COLS];
  106. char showboard[ROWS][COLS];
  107. Initboard(mineboard, ROWS, COLS, '0');
  108. Initboard(showboard, ROWS, COLS, '*');
  109. Displayboard(showboard, ROW, COL);
  110. Setmine(mineboard, ROW, COL);
  111. FindSets(mineboard, showboard, ROW, COL);
  112. }
  113. int main()
  114. {
  115. int input = 0;
  116. do
  117. {
  118. menu();
  119. printf("请输入:->");
  120. scanf("%d", &input);
  121. switch (input)
  122. {
  123. case 1:
  124. game();
  125. break;
  126. case 0:
  127. printf("结束游戏\n");
  128. break;
  129. default:
  130. printf("重新输入\n");
  131. }
  132. } while (input);
  133. return 0;
  134. }

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

闽ICP备14008679号