C语言实现扫雷(自动排查),递归展开

简介: C语言实现扫雷(自动排查),递归展开

1992年4月6日,扫雷和纸牌空当接龙等小游戏搭载在Windows 3.1系统中与用户见面,主要目的是让用户训练使用鼠标。这个游戏的玩法很简单,有初级、中级、高级和自定义等模式,雷区中随机布置一定数量的地雷,玩家需要尽快找出所有不是地雷的方块,但不许踩到地雷

image.png

扫雷:当选择排除的坐标没有设置雷,就会显示出周围有几个雷,若是周围八个方向都没有雷的话就开始自动展开,依次判断周围的八个坐标

但这里有一个边界问题:如果排除的是如图的四个位置,那么往周围八个坐标进行遍历的时候就有数组越界的风险,这里有两个解决方法:

1:当遇上边界的时候进行判断
2:把棋盘设置大一些,加入是一个9*9的棋盘,那么我们可以开一个11*11的数组,超出的部分全部设置为0,这样就算遍历的时候统计雷的个数也不会影响结果,也不会造成数组越界

由于我们使用的是 C语言,不能使用typedef pair<int,int>PII来将一个数组里存放两个元素,也就是当用户排雷的时候看到的是:

但如果是这样,就无法知道哪里有雷哪里没有雷了

所以可以开两个数组,一个存雷的位置,一个展示给用户

首先进行初始化棋盘:

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

set就是要在该棋盘要设置的参数,比如‘*’  ‘0’这些

比较重要的就是如何实现自动排雷,递归展开

如图,如果以红色圈圈为中心的位置,周围八个坐标围成的正方形都没有雷的话,就自动展开,并且该位置的元素设置为 ‘ ’ (空格),这里以展开蓝色位置为例子,蓝色坐标可以展开的蓝色框框的区域,如果使用递归实现展开的话这里就会有一个问题,红色圈圈位置递归之后,蓝色圈圈位置递归的过程中又递归到了红色圈圈的位置,所以就会造成递归死循环的情况,所以可以添加一些条件:

1. if (show[i][j] == '*')//为*则为没有排查过的,可以展开,防止死递归
2. {
3.      Spread(mine, show, i, j);
4. }

test.c文件

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

game.c文件

1. #pragma once
2. #include"game.h"
3. void InitBoard(char board[ROWS][COLS],int row, int col,char set)
4. {
5.  int i = 0;
6.  printf("\n");
7.  for (i = 0; i < row; i++) 
8.  {
9.    int j = 0;
10.     for (j = 0; j < col; j++)
11.     {
12.       board[i][j] = 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.   for (int j = 0; j <= col; j++)
22.   {
23.     printf("%d ", j);
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. //设置雷
38. void setmine(char mine[ROWS][COLS], int row, int col)
39. {
40.   //假设布置10个雷
41.   int count = EASY_COUNT;
42.   while (count)
43.   {
44.     //生成随机下标
45.     int x = rand() % row + 1;//1->9
46.     int y = rand() % col + 1;//1->9
47.     if (mine[x][y] == '0')
48.     {
49.       mine[x][y] = '1';
50.       count--;
51.     }
52.   }
53. }
54. 
55. int get_mine_count(char show[ROWS][COLS], int x, int y)
56. {
57.   return (show[x - 1][y - 1] + show[x - 1][y] + show[x - 1][y + 1] + show[x][y - 1] +
58.     show[x][y + 1] + show[x + 1][y - 1] + show[x + 1][y] + show[x + 1][y + 1] - 8 * '0');
59. }
60. 
61. void Spread(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
62. {
63.   int n = get_mine_count(mine, x, y);
64.   //边界条件,防止数组越界
65.   if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
66.   {
67.     if (n == 0)//需要展开
68.     {
69.       show[x][y] = ' ';//该点周围没有雷就设置为空格
70.       for (int i = x - 1; i <= x + 1; i++) {
71.         for (int j = y - 1; j <= y + 1; j++) {
72.           if (show[i][j] == '*')//为*则为没有排查过的,可以展开,防止死递归
73.           {
74.             Spread(mine, show, i, j);
75.           }
76.         }
77.       }
78.     }
79.     else {
80.       show[x][y] = n + '0';//字符转为数字
81.     }
82.   }
83. }
84. 
85. void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
86. {
87.   int x = 0, y = 0,win=0;
88.   while (win<row*col-EASY_COUNT)
89.   {
90.     printf("请输入要排查的坐标:>");
91.     scanf("%d %d", &x, &y);
92.     if (x >= 1 && x <= row && y >= 1 && y <= col)
93.     {
94.       if (show[x][y] != '*')
95.       {
96.         printf("该坐标已经被排查过了\n");
97.         continue;
98.       }
99.       if (mine[x][y] == '1')
100.      {
101.        printf("很遗憾,你被炸死了!\n");
102.        DisplayBoard(mine, ROW, COL);
103.        break;
104.      }
105.      else
106.      {
107.        Spread(mine, show,x, y);
108.        win++;
109.        DisplayBoard(show, ROW, COL);
110.      }
111.    }
112.  }
113.  if (win == row * col - EASY_COUNT)
114.  {
115.    printf("恭喜你,排雷成功!\n");
116.  }
117. }

game.h文件

1. #define ROWS 11
2. #define COLS 11
3. #define ROW 9
4. #define COL 9
5. #define EASY_COUNT 10
6. #include<time.h>
7. #include<stdlib.h>
8. #include<stdio.h>
9. 
10. //初始化棋盘
11. void InitBoard(char mine[ROWS][COLS],int row,int col,char set);
12. 
13. //打印棋盘
14. void DisplayBoard(char board[ROWS][COLS], int row, int col);
15. 
16. //设置雷
17. void setmine(char mine[ROWS][COLS],int row, int col);
18. 
19. //获取雷的个数
20. int get_mine_count(char show[ROWS][COLS], int x, int y);
21. 
22. //展开
23. void Spread(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y);
24. 
25. //排查雷
26. void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);


目录
相关文章
|
2月前
|
C语言
扫雷游戏(用C语言实现)
扫雷游戏(用C语言实现)
125 0
|
4月前
|
机器学习/深度学习 C语言
九/十:《初学C语言》— 扫雷游戏实现和函数递归基础
【8月更文挑战第5天】本篇文章用C语言采用多文件编写实现了一个基础的扫雷游戏(附源码),并讲解了关于函数递归的基础概念及其相对应的习题练习(附源码)
46 1
九/十:《初学C语言》— 扫雷游戏实现和函数递归基础
|
2月前
|
机器学习/深度学习 C语言
【c语言】一篇文章搞懂函数递归
本文详细介绍了函数递归的概念、思想及其限制条件,并通过求阶乘、打印整数每一位和求斐波那契数等实例,展示了递归的应用。递归的核心在于将大问题分解为小问题,但需注意递归可能导致效率低下和栈溢出的问题。文章最后总结了递归的优缺点,提醒读者在实际编程中合理使用递归。
71 7
|
2月前
|
C语言
c语言回顾-函数递归(上)
c语言回顾-函数递归(上)
43 2
|
3月前
|
存储 安全 算法
C 语言——实现扫雷小游戏
本文介绍了使用二维数组创建棋盘并实现扫雷游戏的方法。首先,通过初始化数组创建一个9x9的棋盘,并添加行列标识以便操作。接着,利用随机数在棋盘上布置雷。最后,通过判断玩家输入的坐标来实现扫雷功能,包括显示雷的数量和处理游戏胜利或失败的情况。文中提供了完整的代码实现。
56 1
C 语言——实现扫雷小游戏
|
2月前
|
存储 算法 安全
C语言实现扫雷游戏
C语言实现扫雷游戏
|
2月前
|
C语言
初学者指南:使用C语言实现简易版扫雷游戏
初学者指南:使用C语言实现简易版扫雷游戏
44 0
|
2月前
|
C语言
c语言回顾-函数递归(下)
c语言回顾-函数递归(下)
42 0
|
2月前
|
C语言
C语言扫雷游戏(详解)
C语言扫雷游戏(详解)
44 0
|
2月前
|
存储 编译器 C语言
【C语言篇】数组和函数的实践:扫雷游戏(附源码)
【C语言篇】数组和函数的实践:扫雷游戏(附源码)
41 0