当前位置:   article > 正文

【C语言】扫雷小游戏(递归展开版)_扫雷小游戏代码

扫雷小游戏代码

哈喽,大家好,上次我们已经学习了三子棋小游戏,今天我们来学习扫雷小游戏了。

目录

1.游戏介绍

2.函数部分

2.1菜单

2.2game()函数

2.3mian()函数

2.4初始化棋盘

2.5打印棋盘

2.6布置雷

2.7排查雷

2.8统计雷

2.9递归,展开一片区域

3.完整代码展示 


1.游戏介绍

想必大家都玩过扫雷这款小游戏吧?

在一个棋盘上随机摆放数个雷,这些雷用户无法看见,只能一个个将雷排查出来,用户点击一个格子,如果这个格子含有雷,游戏就以失败告终,如果这个格子不是雷,就会在这个格子上显示周围8个格子共有多少个雷,如下图:

 今天我们就用C语言来实现这个扫雷小游戏

2.函数部分

下面是游戏要用到的函数:

  1. //初始化棋盘
  2. void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
  3. //打印棋盘
  4. void DisPlayBoard(char board[ROWS][COLS], int row, int col);
  5. //布置雷
  6. void SetMine(char board[ROWS][COLS], int row, int col);
  7. //排查雷
  8. void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
  9. //统计雷
  10. int GetMineCount(char mine[ROWS][COLS], int x, int y);
  11. //递归,展开一片区域
  12. void DfsMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int row, int col);

2.1菜单

菜单非常简洁,用户输入1表示开始游戏,输入0则退出小游戏

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

2.2game()函数

game()函数包含一个游戏的执行过程,将一些函数组合了起来,形成游戏的完整过程。在这儿我们定义了两个数组,mine数组表示存放的雷,show数组表示存放排查出雷的信息。

  1. void game()
  2. {
  3. char mine[ROWS][COLS];//存放的雷
  4. char show[ROWS][COLS];//存放盘查出雷的信息
  5. //初始化棋盘
  6. //mine数组最开始全是‘0’
  7. //show数组最开始全是‘*’
  8. InitBoard(mine, ROWS, COLS, '0');
  9. InitBoard(show, ROWS, COLS, '*');
  10. DisPlayBoard(show, ROW, COL);
  11. //布置雷
  12. SetMine(mine, ROW, COL);
  13. //排查雷
  14. FindMine(mine, show, ROW, COL);
  15. }

2.3mian()函数

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:
  13. game();
  14. break;
  15. case 0:
  16. system("cls");
  17. printf("退出游戏\n");
  18. break;
  19. default:
  20. printf("选择错误,重新选择\n");
  21. break;
  22. }
  23. } while (input);
  24. }

2.4初始化棋盘

初始化棋盘将两个数组初始化。mine数组全部初始化为‘0’,表示最开始还没有存放雷。show数组最开始初始化为‘*’。

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

2.5打印棋盘

打印棋盘这个步骤很简单,但为了方便玩家,我们顺便把棋盘的行号和列号也打印出来。如下图:

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

2.6布置雷

布置雷就是让电脑随机生成10个不重复的坐标,这些坐标就是雷的位置

  1. void SetMine(char board[ROWS][COLS], int row, int col)
  2. {
  3. //布置十个雷
  4. //随机生成坐标
  5. int count = ESAY_COUNT;
  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. }

2.7排查雷

用户输入要排查的雷的坐标,如果该坐标是雷,就输出"很遗憾,你被炸死了“,否则统计这个位置周围的八个位置雷的数量,存到show数组对应坐标位置里。同时这里扩展了一个递归展开,可以展开一片非雷区域。

  1. void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
  2. {
  3. int x, y;
  4. int win = 0;
  5. while (win < row * col - ESAY_COUNT)
  6. {
  7. system("cls");
  8. DisPlayBoard(show, ROW, COL);
  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. break;
  17. }
  18. else
  19. {
  20. //该位置不是雷,就统计这个坐标周围有几个雷
  21. int count = GetMineCount(mine, x, y);
  22. show[x][y] = count + '0';
  23. if (count == 0)
  24. {
  25. //递归,展开一片区域
  26. DfsMine(mine, show, x, y, ROW, COL);
  27. }
  28. show[x][y] = count + '0';
  29. DisPlayBoard(show, ROW, COL);
  30. win++;
  31. }
  32. }
  33. else
  34. {
  35. printf("坐标非法,重新输入\n");
  36. }
  37. }
  38. if (win == row * col - ESAY_COUNT)
  39. {
  40. printf("恭喜你,排雷成功\n");
  41. }
  42. DisPlayBoard(mine, ROW, COL);
  43. }

2.8统计雷

这个函数只要返回坐标(x,y)周围雷的数量即可。

  1. int GetMineCount(char mine[ROWS][COLS], int x, int y)
  2. {
  3. return (mine[x - 1][y - 1] + mine[x][y - 1] +
  4. mine[x + 1][y - 1] + mine[x + 1][y] +
  5. mine[x + 1][y + 1] + mine[x][y + 1] +
  6. mine[x - 1][y + 1] + mine[x - 1][y] - 8 * '0');
  7. }

2.9递归,展开一片区域

这块可以说是一个扩展的内容了,当我们点到一个周围没有地雷的格子,这些区域就会自动展开。

 这里需要用到函数递归来实现,可以将其看作是一个深度优先搜索

  1. void DfsMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int row, int col)
  2. {
  3. int count= GetMineCount(mine, x, y);
  4. show[x][y] = count + '0';
  5. if (count != 0)
  6. {
  7. return;
  8. }
  9. int xx[] = { 1,1, 1 ,-1,-1,-1,0, 0 };
  10. int yy[] = { 1,0,-1, 0, 1, -1 ,1,-1};
  11. int i = 0;
  12. for (i = 0; i < 8; i++)
  13. {
  14. int dx = x + xx[i];
  15. int dy = y + yy[i];
  16. if (dx >= 1 && dx <= row && dy >= 1 && dy <= col && mine[dx][dy]=='0' && show[dx][dy] == '*')
  17. {
  18. DfsMine(mine, show, dx, dy, ROW, COL);
  19. }
  20. }
  21. }

3.完整代码展示 

game.h文件

  1. #pragma once
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. #include<time.h>
  5. #include<Windows.h>
  6. #define ROW 9
  7. #define COL 9
  8. #define ROWS ROW+2
  9. #define COLS COL+2
  10. #define ESAY_COUNT 10 //布置雷的个数
  11. //初始化棋盘
  12. void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
  13. //打印棋盘
  14. void DisPlayBoard(char board[ROWS][COLS], int row, int col);
  15. //布置雷
  16. void SetMine(char board[ROWS][COLS], int row, int col);
  17. //排查雷
  18. void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
  19. //统计雷
  20. int GetMineCount(char mine[ROWS][COLS], int x, int y);
  21. //递归,展开一片区域
  22. void DfsMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int row, int col);

game.c文件

  1. #include"game.h"
  2. //初始化棋盘
  3. void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
  4. {
  5. int i = 0;
  6. for (i = 0; i < rows; i++)
  7. {
  8. int j = 0;
  9. for (j = 0; j < cols; j++)
  10. {
  11. board[i][j] = set;
  12. }
  13. }
  14. }
  15. //打印棋盘
  16. void DisPlayBoard(char board[ROWS][COLS], int row, int col)
  17. {
  18. int i = 0;
  19. printf("--------扫雷--------\n");
  20. for (i = 0; i <= col; i++)
  21. {
  22. printf("%d ", i);
  23. }
  24. printf("\n");
  25. for (i = 1; i <= row; i++)
  26. {
  27. int j = 0;
  28. printf("%d ", i);
  29. for (j = 1; j <= col; j++)
  30. {
  31. printf("%c ", board[i][j]);
  32. }
  33. printf("\n");
  34. }
  35. }
  36. //布置雷
  37. void SetMine(char board[ROWS][COLS], int row, int col)
  38. {
  39. //布置十个雷
  40. //随机生成坐标
  41. int count = ESAY_COUNT;
  42. while(count)
  43. {
  44. int x = rand() % row + 1;
  45. int y = rand() % col + 1;
  46. if (board[x][y] == '0')
  47. {
  48. board[x][y] = '1';
  49. count--;
  50. }
  51. }
  52. }
  53. //排查雷
  54. void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
  55. {
  56. int x, y;
  57. int win = 0;
  58. while (win < row * col - ESAY_COUNT)
  59. {
  60. system("cls");
  61. DisPlayBoard(show, ROW, COL);
  62. printf("请输入要排查雷的坐标:>");
  63. scanf("%d%d", &x, &y);
  64. if (x >= 1 && x <= row && y >= 1 && y <= col)
  65. {
  66. if (mine[x][y] == '1')
  67. {
  68. printf("很遗憾,你被炸死了\n");
  69. break;
  70. }
  71. else
  72. {
  73. //该位置不是雷,就统计这个坐标周围有几个雷
  74. int count = GetMineCount(mine, x, y);
  75. show[x][y] = count + '0';
  76. if (count == 0)
  77. {
  78. //递归,展开一片区域
  79. DfsMine(mine, show, x, y, ROW, COL);
  80. }
  81. show[x][y] = count + '0';
  82. DisPlayBoard(show, ROW, COL);
  83. win++;
  84. }
  85. }
  86. else
  87. {
  88. printf("坐标非法,重新输入\n");
  89. }
  90. }
  91. if (win == row * col - ESAY_COUNT)
  92. {
  93. printf("恭喜你,排雷成功\n");
  94. }
  95. DisPlayBoard(mine, ROW, COL);
  96. }
  97. //递归,展开一片区域
  98. void DfsMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int row, int col)
  99. {
  100. int count= GetMineCount(mine, x, y);
  101. show[x][y] = count + '0';
  102. if (count != 0)
  103. {
  104. return;
  105. }
  106. int xx[] = { 1,1, 1 ,-1,-1,-1,0, 0 };
  107. int yy[] = { 1,0,-1, 0, 1, -1 ,1,-1};
  108. int i = 0;
  109. for (i = 0; i < 8; i++)
  110. {
  111. int dx = x + xx[i];
  112. int dy = y + yy[i];
  113. if (dx >= 1 && dx <= row && dy >= 1 && dy <= col && mine[dx][dy]=='0' && show[dx][dy] == '*')
  114. {
  115. DfsMine(mine, show, dx, dy, ROW, COL);
  116. }
  117. }
  118. }
  119. //统计雷
  120. int GetMineCount(char mine[ROWS][COLS], int x, int y)
  121. {
  122. return (mine[x - 1][y - 1] + mine[x][y - 1] +
  123. mine[x + 1][y - 1] + mine[x + 1][y] +
  124. mine[x + 1][y + 1] + mine[x][y + 1] +
  125. mine[x - 1][y + 1] + mine[x - 1][y] - 8 * '0');
  126. }

test.c文件

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

游戏效果展示:(为了方便截图,已注释了清屏的代码)

 哈哈哈,这次游戏疏忽大意导致游戏失败了~

总结:今天我们学习了扫雷小游戏,再次使用多文件编程的形式,同时也体验了玩自己所写的游戏,如果我写的有什么的不好之处,请在文章下方给出你宝贵的意见。如果觉得我写的好的话请点个赞赞和关注哦~

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