当前位置:   article > 正文

【C语言】扫雷(保姆级教程+内含源码)_扫雷的代码c语言

扫雷的代码c语言

C系列文章目录


前言

一,模块化编程

二,游戏思路与逻辑

三,实现游戏步骤/过程 

1,菜单界面(menu)

2,实现多行多列扫雷 

        3, 实现多个雷

4,棋盘初始化 

5,棋盘的打印 

6,布置雷的信息 

7,玩家输入雷实现步骤 

8,统计输入坐标周围有多少雷

四,结果运行

五,模块化代码实现 

1、test.c

2、game.c 

3、game.h 


前言

通过本章我们可以学习到使用C语言写的扫雷小游戏,该教程堪称保姆级,小白都可学习


一,模块化编程

  1. 可维护性:模块化编程将代码划分为独立的模块,每个模块负责特定的任务或功能。这样,在需要修改或调试某个功能时,只需关注相关的模块,而不需要涉及整个程序。这大大简化了维护和调试的工作,使得代码更易于理解和修改。

  2. 重用性:模块化编程鼓励开发人员将一些常用的功能封装成模块,然后在不同的项目中重复使用。这样可以避免重复编写相同的代码,减少了开发工作量,提高了开发效率。同时,通过不断重用经过测试和验证的模块,可以提高代码的可靠性和稳定性。

  3. 可扩展性:当需要添加新的功能或修改现有功能时,模块化编程能够提供更好的可扩展性。由于模块之间的依赖关系明确定义和管理,可以单独修改或替换某个模块,而不会影响到其他模块。这种灵活性使得系统更容易适应变化和演化。

  4. 并行开发:模块化编程允许多个开发人员并行工作,每个人负责开发和测试不同的模块。这样可以提高开发效率,缩短项目的开发周期。同时,模块化编程也方便团队协作和沟通,降低了开发过程中的冲突和合并的风险。

  5. 可测试性:模块化编程使得单元测试更容易进行。每个模块都是相对独立的,可以单独测试其功能和性能。这样可以更容易地发现和修复问题,提高软件的质量和稳定性。

总之,模块化编程的优势包括可维护性、重用性、可扩展性、并行开发和可测试性。这些优势使得代码更易于理解、修改和维护,提高了开发效率和软件质量。

在学习扫雷前,我们先了解模块化编程,模块化编程的思想可以让我们更好的进行编程,让我们更好的理解接下来的扫雷过程。

二,游戏思路与逻辑

1.创建菜单函数提醒玩家选择是否玩游戏。

2.创建一个main()函数,让我们选择是否游戏

3.当我们选择玩游戏,就进入一个扫雷的游戏函数

4.我们在游戏函数中,创建两个二维数组,一个让人不知道那个是雷,一个放的雷信息

5.开始对游戏函数进行功能填充

  1. 首先,进行雷的初始化棋盘。
  2. 然后,再打印出雷的初始化棋盘。注意:一定是要先进行 初始化 然后再 打印棋盘。
  3. 接着,就可以布置雷的信息了。
  4. 最后,输入排查雷的坐标。

6.检查出的坐标是不是雷,布置雷存放的是字符(1) 没有放置的是字符(0)
7.输入坐标的时候一共有④种情况:《很遗憾,你被炸死了》、《非法坐标了,请重新输入》、《该坐标被占用,请重新输入》、《恭喜你,排雷成功》 
8.然后,再回到步骤①,是否选择 进入游戏 以及 退出游戏

三,实现游戏步骤/过程 

1,菜单界面(menu)

菜单界面函数实际上就像是我们的一个界面,就好比是游戏的界面目录,餐馆当中的菜单。一样的道理。这个是库函数就有的我们只需要直接引用下即可。示例代码如下

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

2,实现多行多列扫雷 

  1. #define ROW 9
  2. #define COL 9//现实棋盘的行数
  3. #define ROWS ROW+2//初始化棋盘的行数,是为了后面的统计雷的方便
  4. #define COLS COL+2

#define 宏定义在这里的好处:

1,方便以后程序的修改,不用以后对程序进行修改时,每个相同的变量都改变,只需对宏定义上进行修改。
2,提高程序的运行效率,更加方便模块化。

3, 实现多个雷

#define EASY_COUNT 10//存放10个雷

我们只需要改一下EASY_COUNT后面的数字,就可以让我们更改有存放多少雷。

4,棋盘初始化 

打印棋盘,本质上是打印数组的内容。如下所示

  1. //初始化棋盘
  2. void InitBoard(char board[ROWS][COLS], int 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字符,初始化数组
  11. }
  12. }
  13. }

char set 是实参传递到形参的字符。

 实参数组名 行 可以进行省略,但是 列 不能进行省略。 

5,棋盘的打印 

打印棋盘,本质上是打印数组的内容。

  1. //打印棋盘
  2. void DisplayBoard(char board[ROWS][COLS], int row, int col)
  3. {
  4. int i = 0;
  5. int j = 0;
  6. printf("----------扫雷-----------\n");
  7. for (i = 0; i <= row; i++)
  8. {
  9. printf("%d ", i);//打印提醒行
  10. }
  11. for (i = 1; i <= row; i++)
  12. {
  13. printf("\n");
  14. printf("%d ", i);//打印提醒列
  15. for (j = 1; j <= col; j++)
  16. {
  17. printf("%c ", board[i][j]);//传参的字符打印
  18. }
  19. }
  20. printf("\n----------扫雷-----------\n");
  21. }

效果图如下:

6,布置雷的信息 

在存放雷的数组内布置雷。

  1. //设置雷
  2. void SetMine(char board[ROWS][COLS], int row, int col)
  3. {
  4. int count = Lie;
  5. while(count)
  6. {
  7. int x = rand() % row + 1;//横坐标1~9
  8. int y = rand() % col + 1;//纵坐标1~9
  9. if (board[x][y] == '0')
  10. {
  11. board[x][y] = '1';//存放雷
  12. count--;
  13. }
  14. }
  15. }

这里还用到了一个知识点【随机数】

在实际开发中,我们往往需要一定范围内的随机数,过大或者过小都不符合要求,那么,如何产生一定范围的随机数呢?我们可以利用取模的方法:

int a = rand() % 10;    //产生0~9的随机数,注意10会被整除
如果要规定上下限:
int a = rand() % 30 + 11;    //产生11~41的随机数
分析:取模即取余,rand()%30+11 我们可以看成两部分:rand()%30 是产生 0~30 的随机数,后面+11保证 a 最小只能是 11,最大就是 30+11=41

使用 <time.h> 头文件中的 time() 函数即可得到当前的时间(精确到秒),就像下面这样:

srand((unsigned)time(NULL));

7,玩家输入雷实现步骤 

这里的玩家输入坐标,在玩家输入下棋的时候,定义了个静态局部变量,在执行代码的时候。玩游戏的时候会提醒一次, 输入第一个坐标记得空一格!每次进入游戏只有一次,这里主要就是用到了 静态局部变量 就可以保证上一次的值不会被销毁。

检查坐标处是不是雷,布置存放的是字符'1',没有放置雷存放的是字符'0'。

判断坐标输入合法性几种情况:

1.很遗憾,你被炸死了!
2.该坐标非法了,请重新输入。
3.该坐标被占用,请重新输入。
4.恭喜你,排雷成功

  1. //排查雷
  2. void FindMine(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col)
  3. {
  4. int x = 0;
  5. int y = 0;
  6. int win = 0;
  7. while (win < row * col - Lie)
  8. {
  9. printf("请输入坐标:>");
  10. scanf("%d %d", &x,&y);
  11. if (x >= 1 && x <= row && y >= 1 && y <= col)
  12. {
  13. if (show[x][y] != '*')
  14. {
  15. printf("该坐标被占用,请重新输入:>");
  16. }
  17. else
  18. {
  19. if (mine[x][y] == '1')
  20. {
  21. printf("很抱歉,你被炸死了");
  22. DisplayBoard(mine, ROW, COL);
  23. break;
  24. }
  25. else
  26. {
  27. int count = get_mine(mine, x, y);
  28. show[x][y] = count + '0';
  29. DisplayBoard(show, ROW, COL);
  30. win++;
  31. }
  32. }
  33. }
  34. else
  35. {
  36. printf("该坐标非法,请重新输入:>");
  37. }
  38. }
  39. if (win == row * col - Lie)
  40. {
  41. printf("恭喜你,扫雷成功\n");
  42. DisplayBoard(mine, ROW, COL);
  43. }
  44. }

8,统计输入坐标周围有多少雷

  1. //统计雷
  2. int get_mine(char board[ROWS][COLS], int x, int y)
  3. {
  4. return (board[x - 1][y - 1] +
  5. board[x - 1][y] +
  6. board[x - 1][y + 1] +
  7. board[x + 1][y + 1] +
  8. board[x + 1][y] +
  9. board[x + 1][y - 1] +
  10. board[x][y - 1] +
  11. board[x][y + 1] - 8 * '0');//统计坐标周围多少雷
  12. }

四,结果运行

我们将存放80个雷,方便我们测试功能。

五,模块化代码实现 

1、test.c

测试游戏的逻辑。

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include "game.h"
  3. mnue()
  4. {
  5. printf("*******-------扫雷----------********\n");
  6. printf("******* 1.play ********\n");
  7. printf("******* 0.exit ********\n");
  8. printf("*******-------扫雷----------********\n");
  9. }
  10. void game()
  11. {
  12. char mine[ROWS][COLS] = { 0 };
  13. char show[ROWS][COLS] = { 0 };
  14. //初始化棋盘
  15. InitBoard(mine, ROWS, COLS, '0');
  16. InitBoard(show, ROWS, COLS, '*');
  17. //设置雷
  18. SetMine(mine, ROW, COL);
  19. //打印棋盘
  20. DisplayBoard(show, ROW, COL);
  21. //排查雷
  22. FindMine(show, mine, ROW, COL);
  23. }
  24. int main()
  25. {
  26. int input = 0;
  27. do
  28. {
  29. mnue();
  30. printf("请选择:>");
  31. scanf("%d", &input);
  32. switch (input)
  33. {
  34. case 1:
  35. game();
  36. break;
  37. case 0:
  38. printf("退出游戏\n");
  39. break;
  40. default:
  41. printf("请重新选择:");
  42. break;
  43. }
  44. } while (input);
  45. return 0;
  46. }

2、game.c 

游戏和相关函数实现。

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include "game.h"
  3. //初始化棋盘
  4. void InitBoard(char board[ROWS][COLS], int 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字符,初始化数组
  13. }
  14. }
  15. }
  16. //打印棋盘
  17. void DisplayBoard(char board[ROWS][COLS], int row, int col)
  18. {
  19. int i = 0;
  20. int j = 0;
  21. printf("----------扫雷-----------\n");
  22. for (i = 0; i <= row; i++)
  23. {
  24. printf("%d ", i);//打印提醒行
  25. }
  26. for (i = 1; i <= row; i++)
  27. {
  28. printf("\n");
  29. printf("%d ", i);//打印提醒列
  30. for (j = 1; j <= col; j++)
  31. {
  32. printf("%c ", board[i][j]);//传参的字符打印
  33. }
  34. }
  35. printf("\n----------扫雷-----------\n");
  36. }
  37. //设置雷
  38. void SetMine(char board[ROWS][COLS], int row, int col)
  39. {
  40. int count = Lie;
  41. while(count)
  42. {
  43. int x = rand() % row + 1;//横坐标1~9
  44. int y = rand() % col + 1;//纵坐标1~9
  45. if (board[x][y] == '0')
  46. {
  47. board[x][y] = '1';//存放雷
  48. count--;
  49. }
  50. }
  51. }
  52. //统计雷
  53. int get_mine(char board[ROWS][COLS], int x, int y)
  54. {
  55. return (board[x - 1][y - 1] +
  56. board[x - 1][y] +
  57. board[x - 1][y + 1] +
  58. board[x + 1][y + 1] +
  59. board[x + 1][y] +
  60. board[x + 1][y - 1] +
  61. board[x][y - 1] +
  62. board[x][y + 1] - 8 * '0');//统计坐标周围多少雷
  63. }
  64. //排查雷
  65. void FindMine(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col)
  66. {
  67. int x = 0;
  68. int y = 0;
  69. int win = 0;
  70. while (win < row * col - Lie)
  71. {
  72. printf("请输入坐标:>");
  73. scanf("%d %d", &x,&y);
  74. if (x >= 1 && x <= row && y >= 1 && y <= col)
  75. {
  76. if (show[x][y] != '*')
  77. {
  78. printf("该坐标被占用,请重新输入:>");
  79. }
  80. else
  81. {
  82. if (mine[x][y] == '1')
  83. {
  84. printf("很抱歉,你被炸死了");
  85. DisplayBoard(mine, ROW, COL);
  86. break;
  87. }
  88. else
  89. {
  90. int count = get_mine(mine, x, y);
  91. show[x][y] = count + '0';
  92. DisplayBoard(show, ROW, COL);
  93. win++;
  94. }
  95. }
  96. }
  97. else
  98. {
  99. printf("该坐标非法,请重新输入:>");
  100. }
  101. }
  102. if (win == row * col - Lie)
  103. {
  104. printf("恭喜你,扫雷成功\n");
  105. DisplayBoard(mine, ROW, COL);
  106. }
  107. }

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 Lie 80
  10. //初始化棋盘
  11. void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
  12. //打印棋盘
  13. void DisplayBoard(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 show[ROWS][COLS], char mine[ROWS][COLS], int row, int col);


总结

本篇文章详细的,有体系的介绍了扫雷的结构,方便我们小白的更加理解C语言的数组。

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

闽ICP备14008679号