当前位置:   article > 正文

C语言:扫雷游戏

C语言:扫雷游戏

目录

1.了解扫雷游戏的规则:

2.在编译器上设计扫雷游戏:

(1)写入主函数: 

(2)写入菜单及菜单选择的函数: 

(3)写入完成扫雷游戏的函数game() 

3.完整代码

4.代码测试

 扫雷游戏是我们这一代人小时候都会玩的游戏,那如何用C语言来实现一个简单的扫雷游戏呢?

让我们一起来逐步学习吧 ~

1.了解扫雷游戏的规则:

    (1)游戏可以通过菜单实现继续玩或者退出游戏

    (2)扫雷游戏的棋盘是9*9的格子

    (3)默认随机布置10个雷

    (4)可以排查雷

              a.如果位置不是雷,就显示周围有几个雷

              b.如果位置是雷,就炸死游戏结束

              c.把除10个类之外的所有非雷都找出来,排雷成功,游戏结束

棋盘示例:

2.在编译器上设计扫雷游戏:

在进行扫雷游戏的设计时,应在同一项目下加入三个文件(如图):

首先,在test.c文件中完成游戏的测试逻辑。

为避免所有的指令全部位于主函数之内,可以采用函数调用,来使程序的内容整体更加清晰、明确。

确定头文件:

#include<stdio.h>
(1)写入主函数: 
  1. int main()
  2. {
  3. test();//测试逻辑
  4. return 0;
  5. }
(2)写入菜单及菜单选择的函数: 

 一般游戏的开始总会有菜单界面进行选择。

例如:“开始游戏”和“结束游戏”。用户通过选择“1”,“0”来开始或结束游戏。

该选择的实现可以通过switch循环语句实现

想多次进行游戏则可以通过do......while循环语句来实现:

  1. void test
  2. {
  3. do
  4. {
  5. menu();//menu为菜单界面
  6. } while ();
  7. }

 此时进行修整后的菜单及选择界面的代码及运行结果如下:

  1. #include<stdio.h>
  2. void menu()//仅用于打印菜单
  3. {
  4. printf("***************************\n");
  5. printf("******* 1. play *******\n");
  6. printf("******* 0. exit *******\n");
  7. printf("***************************\n");
  8. }
  9. void test()//用于菜单选择的实现
  10. {
  11. int input = 0;
  12. do
  13. {
  14. menu();
  15. printf("请选择:>");
  16. scanf_s("%d", &input);//下一步识别1、0、其他数
  17. switch(input)
  18. {
  19. case 1:
  20. printf("扫雷\n");//输入值为 1 开始游戏
  21. break;
  22. case 0:
  23. printf("游戏结束,退出游戏\n");//输入值为 0 结束游戏
  24. break;
  25. default:
  26. printf("选择错误,重新选择\n");//输入其他数,重新进行选择
  27. }
  28. } while (input);//只有当输入值为 0 时才停止循环,否则将一直进行循环
  29. }
  30. int main()
  31. {
  32. test();
  33. return 0;

这样游戏的菜单界面就设计好啦~

那我们开始游戏的时候可就不能只打印“扫雷”两个字喽!要将它换成我们的游戏函数game()了 

(3)写入完成扫雷游戏的函数game() 

假设,对棋盘进行排查,则会发现

在排查(2,5)这个坐标时,我们访问周围的一圈八个黄色位置,统计周围雷的个数是1

在排查(8,6)这个坐标时,我们访问周围的一圈八个黄色位置,统计周围雷的个数时,最下面的三个坐标就会越界,为了避免越界的情况,我们在设计时应该给数组扩大一圈,而我们的雷仍应该布置在9*9的坐标上,即创建成11*11的区域。

(起始棋盘) 

 

(优化后的棋盘) 

a.规定雷的标记 

从上面的棋盘中我们设定了:‘1’为雷 ‘0’为非雷 但当我们将雷排出时,原本‘0’所在的位置见会被改写成‘1’代表被排除,但此时将会与用‘1’代表的雷混淆。那么此时~聪明的我们肯定会想到解决的办法,那就是--设置两个数组,一组用来设置雷,一组用来排雷。如图:

 b.在设计棋盘

时要对棋盘进行初始化,为了方便之后对游戏的拓展,我们还需要在game.h的头文件中设计:

  1. #pragma once
  2. #define ROW 9//行
  3. #define COL 9//列
  4. #define ROWS ROW+2
  5. #define COLS COL+2

此时要记得在文件test.c中声明我们自己的头文件,即:

#include "game.h" 

要注意声明自己的头文件时不能使用<>要使用""

 c.初始化棋盘

时利用文件game.c执行棋盘的初始化,此时,文件test.c中的game函数中应该如下

  1. void game()
  2. {
  3. char mine[ROWS][COLS] = { 0 };//数组全部初始化为'0'
  4. char show[ROWS][COLS] = { 0 };//数组全部初始化为'*'
  5. //初始化棋盘
  6. InitBoard(mine, ROWS, COLS, '0');
  7. InitBoard(show, ROWS, COLS, '*');
  8. }

此时的game.c文件中的InitBoard函数应该如下: 

  1. #include"game.h"
  2. void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
  3. {
  4. int i = 0;
  5. for (i = 0; i < rows; i++)
  6. {
  7. int j = 0;
  8. for (j = 0; j < cols; j++)
  9. {
  10. board[i][j] = set;
  11. }
  12. }
  13. }
d. 打印棋盘

打印棋盘时主要是打印show函数中的棋盘,则在game.h文件中声明打印棋盘的函数,并在game.c文件中写入初步打印棋盘的函数。

  1. void DispiayBoard(char board[ROWS][COLS], int row, int col);
  2. //因为棋盘只用打印9*9棋盘,所以只用传输9行9列
  1. void DispiayBoard(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. printf("%d ", i);
  13. int j = 0;
  14. for (j = 1; j <= col; j++)
  15. printf("%c ", board[i][j]);
  16. printf("\n");
  17. }
  18. }

此时的运行结果如图: 

e. 布置雷

布置雷是在数组mine中布置的,这些雷在我们的游戏条件下是10个,而且是随机的,所以在test.c文件中的game函数中需要添加一个布置雷的函数SetMine并在game.c文件中确定函数。

因为要使用随机数所以在game.h文件中需要包含库函数:

#include<stdlib.h>

#include<time.h>

#define EASY_COUNT 10//确定雷的个数

  1. void SetMine(char board[ROWS][COLS], int row, int col)
  2. {
  3. int count = EASY_COUNT;//确定雷的个数
  4. while (count)
  5. {
  6. int x = rand() % row + 1;
  7. int y = rand() % col + 1;
  8. if (board[x][y] == '0')
  9. {
  10. board[x][y] = '1';
  11. count--;
  12. }
  13. }
  14. }

 d.排除雷需要同时借助mine和show数组,构建函数FindMine进行排查。

如图 即为此处的排除雷的函数代码:

  1. int GetMineCount(char mine[ROWS][COLS], int x, int y)
  2. {
  3. return(mine[x - 1][y] +
  4. 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. 8 * '0');
  12. }
  13. void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
  14. {
  15. int x = 0;
  16. int y = 0;
  17. int win = 0;//用来记录已经排除掉的坐标的个数,以便及时停止游戏
  18. while (win < row * col - EASY_COUNT)
  19. {
  20. printf("请输入要排查的坐标:>");
  21. scanf("%d %d", &x, &y);
  22. if (x >= 1 && x <= row && y >= 1 && y <= col)//判断坐标是否有效
  23. {
  24. if (mine[x][y] == '1')//判断是否是雷
  25. {
  26. printf("很遗憾,你被炸死了\n");
  27. DispiayBoard(mine, ROW, COL);
  28. break;
  29. }
  30. else
  31. {
  32. int count = GetMineCount(mine, x, y);//增加一个函数,用来计算输入的坐标周围八个位置中总共的雷的个数
  33. show[x][y] = count + '0';
  34. DispiayBoard(show, ROW, COL);//每排除一个便,打印一次此时的棋盘
  35. win++;//每排除一个便加一
  36. }
  37. }
  38. else
  39. {
  40. printf("坐标非法,重新输入\n");
  41. }
  42. }
  43. if (win == row * col - EASY_COUNT)//所有不是雷的坐标全部找到,结束游戏
  44. {
  45. printf("恭喜你,排雷成功\n");
  46. DispiayBoard(mine, ROW, COL);
  47. }
  48. }

此时所有的代码都已准备就绪:

3.完整代码
game.h
  1. #pragma once
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. #include<time.h>
  5. #define ROW 9//行
  6. #define COL 9//列
  7. #define ROWS ROW+2
  8. #define COLS COL+2
  9. #define EASY_COUNT 10
  10. //初始化棋盘
  11. void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
  12. //打印棋盘
  13. void DispiayBoard(char board[ROWS][COLS], int row, int col);
  14. //布置雷
  15. void SetMine(char board[ROWS][COLS], int row, int col);
  16. //排除雷
  17. void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
game.c
  1. #include"game.h"
  2. void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
  3. {
  4. int i = 0;
  5. for (i = 0; i < rows; i++)
  6. {
  7. int j = 0;
  8. for (j = 0; j < cols; j++)
  9. {
  10. board[i][j] = set;
  11. }
  12. }
  13. }
  14. void DispiayBoard(char board[ROWS][COLS], int row, int col)
  15. {
  16. int i = 0;
  17. printf("-------扫雷游戏-------\n");//美化棋盘
  18. for (i = 0; i <= col; i++)
  19. {
  20. printf("%d ", i);//打印列号
  21. }
  22. printf("\n");
  23. for (i = 1; i <= row; i++)
  24. {
  25. printf("%d ", i);//打印行号
  26. int j = 0;
  27. for (j = 1; j <= col; j++)
  28. printf("%c ", board[i][j]);//打印棋盘
  29. printf("\n");
  30. }
  31. }
  32. void SetMine(char board[ROWS][COLS], int row, int col)
  33. {
  34. int count = EASY_COUNT;
  35. while (count)//确保只有规定数量的雷
  36. {
  37. int x = rand() % row + 1;
  38. int y = rand() % col + 1;
  39. if (board[x][y] == '0')//保证都是在棋盘大小之内的范围
  40. {
  41. board[x][y] = '1';
  42. count--;//每布置一个便减一
  43. }
  44. }
  45. }
  46. int GetMineCount(char mine[ROWS][COLS], int x, int y)
  47. {
  48. return(mine[x - 1][y] +
  49. mine[x - 1][y - 1] +
  50. mine[x][y - 1] +
  51. mine[x + 1][y - 1] +
  52. mine[x + 1][y] +
  53. mine[x + 1][y + 1] +
  54. mine[x][y + 1] +
  55. mine[x - 1][y + 1] -
  56. 8 * '0');
  57. }
  58. void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
  59. {
  60. int x = 0;
  61. int y = 0;
  62. int win = 0;//用来记录已经排除掉的坐标的个数,以便及时停止游戏
  63. while (win < row * col - EASY_COUNT)
  64. {
  65. printf("请输入要排查的坐标:>");
  66. scanf("%d %d", &x, &y);
  67. if (x >= 1 && x <= row && y >= 1 && y <= col)//判断坐标是否有效
  68. {
  69. if (mine[x][y] == '1')//判断是否是雷
  70. {
  71. printf("很遗憾,你被炸死了\n");
  72. DispiayBoard(mine, ROW, COL);
  73. break;
  74. }
  75. else
  76. {
  77. int count = GetMineCount(mine, x, y);//增加一个函数,用来计算输入的坐标周围八个位置中总共的雷的个数
  78. show[x][y] = count + '0';
  79. DispiayBoard(show, ROW, COL);//每排除一个便,打印一次此时的棋盘
  80. win++;//每排除一个便加一
  81. }
  82. }
  83. else
  84. {
  85. printf("坐标非法,重新输入\n");
  86. }
  87. }
  88. if (win == row * col - EASY_COUNT)//所有不是雷的坐标全部找到,结束游戏
  89. {
  90. printf("恭喜你,排雷成功\n");
  91. DispiayBoard(mine, ROW, COL);
  92. }
  93. }
test.c
  1. #include"game.h"
  2. void menu()//仅用于打印菜单
  3. {
  4. printf("***************************\n");
  5. printf("******* 1. play *******\n");
  6. printf("******* 0. exit *******\n");
  7. printf("***************************\n");
  8. }
  9. void game()//完成扫雷游戏
  10. {
  11. char mine[ROWS][COLS] = { 0 };//数组全部初始化为'0'
  12. char show[ROWS][COLS] = { 0 };//数组全部初始化为'*'
  13. //初始化棋盘
  14. InitBoard(mine, ROWS, COLS, '0');
  15. InitBoard(show, ROWS, COLS, '*');
  16. //布置雷
  17. SetMine(mine, ROW, COL);//先布置雷,再打印雷更符合逻辑
  18. //打印棋盘
  19. DispiayBoard(show, ROW, COL);
  20. //排除雷
  21. FindMine(mine, show, ROW, COL);
  22. }
  23. void test()
  24. {
  25. int input = 0;
  26. srand((unsigned int)time(NULL));
  27. do
  28. {
  29. menu();
  30. printf("请选择:>");
  31. scanf("%d", &input);//下一步识别1、0、其他数
  32. switch(input)
  33. {
  34. case 1:
  35. printf("一共有十个雷,请找出");
  36. game();//输入值为 1 开始游戏
  37. break;
  38. case 0:
  39. printf("游戏结束,退出游戏\n");//输入值为 0 结束游戏
  40. break;
  41. default:
  42. printf("选择错误,重新选择\n");//输入其他数,重新进行选择
  43. }
  44. } while (input);//只有当输入值为 0 时才停止循环,否则将一直进行循环
  45. }
  46. int main()
  47. {
  48. test();
  49. return 0;
  50. }
4.代码测试

此时一共有八十一个坐标,而实际上的雷只有十个,如果想要测试代码是否能正常运行到结束,需要,耗费很长时间,若中途游戏失败,还需要重新进行,所以我们要选用更便捷的方式来测试。即:

设置雷的个数为80个,此时只有一个位置不是雷,在进行排雷之前直接显示出雷的位置,即可测试是否可以顺利结束。

如图中的运行结果:


以上便是简易的扫雷游戏的代码设计过程,这只是最简易的,欢迎大家继续拓展呦~

如果代码有用,记得一键三连呦~

在线扫雷游戏:http://www.minesweeper.cn/

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号