当前位置:   article > 正文

C语言 —— 扫雷小游戏详解附源码_c语言扫雷游戏源代码

c语言扫雷游戏源代码

目录

 一.是否进入游戏的判断

二.游戏主体实现

(一).创建棋盘

(二).初始化棋盘

(三).棋盘打印函数

(四).布置雷

(五).玩家排雷

(六).判断游戏状态(输赢等)

 三.最后效果图和原码赠送


 这种类型的小游戏,是对基础知识很好的复习!

实现前准备:

        一 . 了解游戏如何玩

简单版举例:

        一个9*9的棋盘中有10个雷,你要将他们一一排除,直到排除完所有雷,踩到雷你就会死亡。

踩到不是雷的地方,会扫描附近8格方格,并会告诉你这附近8个方格中的雷数。

如:

图中的2附近8个方格中,只有最后两个未排除那他们一定就是雷

 你不信?你踩下去试试:

二.实现前思想

  1. 可以用二维数组来当棋盘
  2. 用1当雷0为非雷,这样可以方便计算附近的雷数
  3. 编写函数,实现输入输出和判断游戏状态的函数

三. 解决代码较多问题

        因为考虑到代码量较多,为了代码的整洁性,可读性,我把代码分成了3个部分

  •         minesweeper.c    ——    用来实现游戏的本身的逻辑
  •         game.c   ——    功能函数的实现
  •         game.h   ——    函数的声明和头文件和宏的等声明

 一.是否进入游戏的判断

不管如何要先进入系统,所有用do while循环实现,然后打印一个菜单给玩家选择:

菜单:

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

 有了菜单玩家要选择,创建input变量,把退出项设为0,input就可以作为循环的表达式,在c语言中0为假1为真,真执行,假不执行,玩家选择0为假喜欢停止退出程序

  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. printf("退出游戏\n");
  17. break;
  18. default:
  19. printf("输入错误请重新选择\n");
  20. }
  21. } while (input);
  22. return 0;
  23. }

二.游戏主体实现

        游戏主体需要实现各种功能,把他们放在game.c文件中,函数、宏、头文件、声明在game.h头文件中

(一).创建棋盘

考虑到如果是边缘的方块要检测,那就非常的不好办了:

 我们干脆做大一圈,但只使用内圈,这样排除起来就方便了:

 定义宏做为二维数组参数:

  1. //控制棋盘大小:
  2. //如:9*9
  3. #define ROW 9
  4. #define COL 9
  5. //实际使用+2保证棋盘大一圈
  6. #define ROWS ROW+2
  7. #define COLS COL+2

创建二维数组,用来做棋盘,由于考虑到1作为了雷,那检测显示附近的雷数如果是1就麻烦了,所以创建两个数组一个用来放雷,一个用来打印和显示附近雷数。

  1. //设计两个数组存放信息
  2. //mine放雷
  3. //show用来打印和附近雷的数量
  4. char mine[ROWS][COLS] = { 0 };
  5. char show[ROWS][COLS] = { 0 };

(二).初始化棋盘

我们把mine放雷:1为雷0为非雷

再把show用来打印和附近的雷数:#为雷*为非雷

实参:

  1. //mine - 全部初始化为 0
  2. //show - 全部初始化为 *
  3. init_board(mine, ROWS, COLS, '0');
  4. init_board(show, ROWS, COLS, '*');

 形参:

  1. //初始化
  2. void init_board(char board[ROWS][COLS], char rows, int cols, char set)
  3. {
  4. int i = 0;
  5. int j = 0;
  6. for (i = 0; i < rows; i++)
  7. {
  8. for (j = 0; j < cols; j++)
  9. {
  10. board[i][j] = set;//set为传过来的图案如:0或*
  11. }
  12. }
  13. }

 函数声明放在game.h文件中:

后面就不说函数定义了都跟函数形参那一排一样

  1. //初始化棋盘
  2. void init_board(char board[ROWS][COLS], int rows, int cols, char set);

(三).棋盘打印函数

初始化好了棋盘,我们需要一个能够随时打印棋盘的函数:

实参:

display_board(show, ROW, COL);

形参:

  1. //棋盘打印
  2. void display_board(char board[ROWS][COLS], int row, int col)
  3. {
  4. int i = 0;
  5. int j = 0;
  6. for (i = 0; i <= row; i++)//打印坐标行
  7. {
  8. printf("%d ",i);
  9. }
  10. printf("\n");
  11. for (i = 1; i <= row; i++)
  12. {
  13. printf("%d ", i);//打印坐标列
  14. for (j = 1; j <= col; j++)
  15. {
  16. printf("%c ", board[i][j]);
  17. }
  18. printf("\n");
  19. }
  20. }

效果:

 其余部分计是棋盘

(四).布置雷

棋盘出来了但里面还没有雷

这里就要介绍前面主函数中的:

	srand((unsigned int)time(NULL));

了解:

#include <stdlib.h>

1.rand库函数 生成一个随机数 在调用rend之前,需要先调用srand随机生成器

2.srand 设置一个随机的起点

  1. //(强制类型转换unsigned int)是因为srand里的数据类型是unsigned int
  2. //NULL是因为time是返回当前时间(秒数),这里并不需要他返回
  3. srand((unsigned int)time(NULL));

 这里我们再定义一个宏可以随意的控制雷的数量:

  1. //控制雷数:
  2. #define EASY_COUNT 10

 函数实现:

  1. //布置雷
  2. void set_mine(char mine[ROWS][COLS], int row, int col)
  3. {
  4. int count = EASY_COUNT;
  5. while (count)
  6. {
  7. //EASY_COUNT = 10
  8. //随机值 % 9 = 0 - 8的数字
  9. //+ 1 产生 1 - 9 的数
  10. //刚好符合我们要使用的二维数组的下标
  11. int x = rand() % row + 1;
  12. int y = rand() % col + 1;
  13. if (mine[x][y] == '0')
  14. {
  15. mine[x][y] = '1';
  16. count--;
  17. }
  18. }
  19. }

效果:

(五).玩家排雷

由于我们存放的是字符数字 如: ' 3 '

他的ASCII码并不是3看图:

 但是可以发现这样的规律:

0 - 9字符的ASCII码减去0得原数字

' 2 ' - ' 0 ' = 50 - 48 = 2

那我们就可以把周围排查的数加起来的和,减去 8(排查的范围) * 字符 ' 0 '  = 周围的雷数

这样就有了排查雷的函数:

  1. //排查周围的雷
  2. int get_mine_count(char mine[ROWS][COLS], int x, int y)
  3. {
  4. return (mine[x - 1][y] +
  5. mine[x - 1][y - 1] +
  6. mine[x][y - 1] +
  7. mine[x + 1][y - 1] +
  8. mine[x + 1][y] +
  9. mine[x + 1][y + 1] +
  10. mine[x][y + 1] +
  11. mine[x - 1][y + 1] - 8 * '0');
  12. }

提醒

  • mine数组是放雷的
  • show是用来显示的
  1. //玩家排除雷,初步
  2. void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
  3. {
  4. int x = 0;
  5. int y = 0;
  6. int win = 0;
  7. while (1)
  8. {
  9. printf("请输入排雷坐标:>");
  10. scanf("%d %d", &x, &y);
  11. if (x >= 1 && x <= row && y >= 1 && y <= col)
  12. {
  13. int count = get_mine_count(mine, x, y);//设计一个函数来排查周围8个方格中的雷
  14. show[x][y] = count + '0';
  15. display_board(show, ROW, COL);
  16. }
  17. else
  18. {
  19. printf("非法坐标,请重新输入\n");
  20. }
  21. }
  22. }

效果: 

 可以看到,排查的位置周围有两个雷

(六).判断游戏状态(输赢等)

 

在这段代码中我们只判断了,输入的值超出界限的情况,但是还有许多游戏状态:

  • 还有坐标重复
  • 被雷炸死
  • 还有最后胜利的状态

加入判断:

  1. //排雷
  2. void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
  3. {
  4. int x = 0;
  5. int y = 0;
  6. int win = 0;
  7. // win依依排查到最后等于71不在 < 9 * 9 - 10 = 71
  8. while (win < row * col - EASY_COUNT)//当win排查出所有雷,停止循环
  9. {
  10. printf("请输入排雷坐标:>");
  11. scanf("%d %d", &x, &y);
  12. if (x >= 1 && x <= row && y >= 1 && y <= col)
  13. {
  14. if (show[x][y] == '*')
  15. {
  16. if (mine[x][y] == '1')
  17. {
  18. printf("非常遗憾你被炸死了\n");
  19. display_board(mine, ROW, COL);
  20. break;
  21. }
  22. else
  23. {
  24. //设计一个函数来排查周围8个方格中的雷
  25. int count = get_mine_count(mine, x, y);
  26. show[x][y] = count + '0';//得出来的值+‘ 0 ’,就得数字字符
  27. display_board(show, ROW, COL);//打印出来看
  28. win++;//记录排查正确的数量
  29. }
  30. }
  31. else
  32. {
  33. printf("请重新输入,该坐标已输入\n");
  34. }
  35. }
  36. else
  37. {
  38. printf("非法坐标,请重新输入\n");
  39. }
  40. }
  41. if (win == row * col - EASY_COUNT)
  42. {
  43. printf("恭喜你排除了所有雷\n");
  44. display_board(mine, ROW, COL);
  45. }
  46. }

 三.最后效果图和原码赠送

        这里为了给大家展示我把雷的数量改到79,把mine放雷的棋盘一起打印出来,给大家看游戏各个状态

 

 胜利状态:

重复输入状态:

超出范围状态:

 炸死状态:

 源码:

minesweeper.c

  1. #define _CRT_SECURE_NO_WARNINGS 1
  2. //扫雷实现
  3. #include"game.h"
  4. //菜单
  5. void menu()
  6. {
  7. printf("*****************************\n");
  8. printf("******** 1 . play *******\n");
  9. printf("******** 0 . exit *******\n");
  10. printf("*****************************\n");
  11. }
  12. void game()
  13. {
  14. //设计两个数组存放信息
  15. //mine放雷
  16. //show用来打印和附近雷的数量
  17. char mine[ROWS][COLS] = { 0 };
  18. char show[ROWS][COLS] = { 0 };
  19. //mine - 全部初始化为 0
  20. //show - 全部初始化为 *
  21. init_board(mine, ROWS, COLS, '0');
  22. init_board(show, ROWS, COLS, '*');
  23. //打印棋盘
  24. /*display_board(mine, ROW, COL);
  25. display_board(show, ROW, COL);*/
  26. //布置雷
  27. set_mine(mine, ROW, COL);
  28. /*display_board(mine, ROW, COL);*/
  29. display_board(show, ROW, COL);
  30. //排雷和游戏状态的判断
  31. find_mine(mine, show, ROW, COL);
  32. }
  33. int main()
  34. {
  35. int input = 0;
  36. srand((unsigned int)time(NULL));
  37. do
  38. {
  39. menu();
  40. printf("请选择");
  41. scanf("%d", &input);
  42. switch (input)
  43. {
  44. case 1 :
  45. game();
  46. break;
  47. case 0 :
  48. printf("退出游戏\n");
  49. break;
  50. default:
  51. printf("输入错误请重新选择\n");
  52. }
  53. } while (input);
  54. return 0;
  55. }

game.c

  1. #define _CRT_SECURE_NO_WARNINGS 1
  2. #include"game.h"
  3. //初始化
  4. void init_board(char board[ROWS][COLS], char rows, int cols, char set)
  5. {
  6. int i = 0;
  7. int j = 0;
  8. for (i = 0; i < rows; i++)
  9. {
  10. for (j = 0; j < cols; j++)
  11. {
  12. board[i][j] = set;//set为传过来的图案如:0或*
  13. }
  14. }
  15. }
  16. //棋盘打印
  17. void display_board(char board[ROWS][COLS], int row, int col)
  18. {
  19. int i = 0;
  20. int j = 0;
  21. for (i = 0; i <= row; i++)//打印坐标行
  22. {
  23. printf("%d ", i);
  24. }
  25. printf("\n");
  26. for (i = 1; i <= row; i++)
  27. {
  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 set_mine(char mine[ROWS][COLS], int row, int col)
  38. {
  39. int count = EASY_COUNT;
  40. while (count)
  41. {
  42. //EASY_COUNT = 10
  43. //随机值 % 9 = 0 - 8的数字
  44. //+ 1 产生 1 - 9 的数
  45. //刚好符合我们要使用的二维数组的下标
  46. int x = rand() % row + 1;
  47. int y = rand() % col + 1;
  48. if (mine[x][y] == '0')
  49. {
  50. mine[x][y] = '1';
  51. count--;
  52. }
  53. }
  54. }
  55. //排查周围的雷
  56. int get_mine_count(char mine[ROWS][COLS], int x, int y)
  57. {
  58. return (mine[x - 1][y] +
  59. mine[x - 1][y - 1] +
  60. mine[x][y - 1] +
  61. mine[x + 1][y - 1] +
  62. mine[x + 1][y] +
  63. mine[x + 1][y + 1] +
  64. mine[x][y + 1] +
  65. mine[x - 1][y + 1] - 8 * '0');
  66. }
  67. //排雷
  68. void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
  69. {
  70. int x = 0;
  71. int y = 0;
  72. int win = 0;
  73. // win依依排查到最后等于71不在 < 9 * 9 - 10 = 71
  74. while (win < row * col - EASY_COUNT)//当win排查出所有雷,停止循环
  75. {
  76. printf("请输入排雷坐标:>");
  77. scanf("%d %d", &x, &y);
  78. if (x >= 1 && x <= row && y >= 1 && y <= col)
  79. {
  80. if (show[x][y] == '*')
  81. {
  82. if (mine[x][y] == '1')
  83. {
  84. printf("非常遗憾你被炸死了\n");
  85. display_board(mine, ROW, COL);
  86. break;
  87. }
  88. else
  89. {
  90. int count = get_mine_count(mine, x, y);//设计一个函数来排查周围8个方格中的雷
  91. show[x][y] = count + '0';//得出来的值+‘ 0 ’,就得数字字符
  92. display_board(show, ROW, COL);//打印出来看
  93. win++;
  94. }
  95. }
  96. else
  97. {
  98. printf("请重新输入,该坐标已输入\n");
  99. }
  100. }
  101. else
  102. {
  103. printf("非法坐标,请重新输入\n");
  104. }
  105. }
  106. if (win == row * col - EASY_COUNT)
  107. {
  108. printf("恭喜你排除了所有雷\n");
  109. display_board(mine, ROW, COL);
  110. }
  111. }
  112. 玩家排除雷,初步
  113. //void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
  114. //{
  115. // int x = 0;
  116. // int y = 0;
  117. // int win = 0;
  118. // while (1)
  119. // {
  120. // printf("请输入排雷坐标:>");
  121. // scanf("%d %d", &x, &y);
  122. // if (x >= 1 && x <= row && y >= 1 && y <= col)
  123. // {
  124. // int count = get_mine_count(mine, x, y);//设计一个函数来排查周围8个方格中的雷
  125. // show[x][y] = count + '0';
  126. // display_board(show, ROW, COL);
  127. // }
  128. // else
  129. // {
  130. // printf("非法坐标,请重新输入\n");
  131. // }
  132. // }
  133. //}

game.h

  1. //控制棋盘大小:
  2. //如:9*9
  3. #define ROW 9
  4. #define COL 9
  5. //实际使用+2保证棋盘大一圈
  6. #define ROWS ROW+2
  7. #define COLS COL+2
  8. //控制雷数:
  9. #define EASY_COUNT 10
  10. #include<stdio.h>
  11. #include<stdlib.h>
  12. #include<time.h>
  13. //初始化棋盘
  14. void init_board(char board[ROWS][COLS], int rows, int cols, char set);
  15. //打印棋盘
  16. void display_board(char board[ROWS][COLS], int row, int col);
  17. //布置雷
  18. void set_mine(char mine[ROWS][COLS], int row, int col);
  19. //排雷
  20. void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

如果这篇博客对你有帮助,一键三连走一波,你们的支持是我最大的动力!!!

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

闽ICP备14008679号