C语言实现简易版的扫雷游戏

目录

在正式讲内容之前先说一说扫雷游戏的规则

首先看一下test.c:

接下来是game.h:

 接下来是game.c:


在正式讲内容之前先说一说扫雷游戏的规则

游戏规则很简单,点击方格,如果是地雷,游戏失败,找到所有地雷游戏胜利

  • .刚开始需要碰运气,只要点开一个区域,就可以正式开始了。

  • 3

    根据现有情况,判断出一定有雷的位置。

  • 4

    进一步计算,因为“2”右边的“1”已经有从属的雷了,所以右边的“2”的正下方没有雷,因此可以判断出左边有两颗雷,满足两个“2”。

  • 5

    红圈表明的“1”已经有一颗确定的雷了,这时只需要把鼠标放在“1”上,按住右键不放,再点一下左键,“1”周围的其他方块就全被点开了。这个小技巧对于提升速度非常有帮助。

  • 6

    左上角的“1”旁边必须有一颗雷,可能在红圈圈住的两个块中,目前还无法确定。但是不论在两个中的哪一个,都从属于“3”,因此“3”周围已经有了三颗雷,“3”左下角的方块可以确定没有雷。

  • 7

    红圈框住的位置肯定有一颗雷,因为“3”周围必须有三颗雷。不论在两个中的哪一个,都从属于“3旁边的“2”,这样“2”就满足两颗雷的条件了。因此“2”左下角的块是没有雷的。

  • 8

    这样一来,“3”下面的两个块可以确定都是有雷的。

  • 9

    把这些有雷的地方标出来,就打开了一片新天地。

  • 10

    再根据现有的条件把确定有雷的地方表明,点开其他的地方。这时我们发现刚才左上角遗留的问题解决了。

  • 11

    重复上面的各种方法,不断推理出,最后就能完成扫雷

 好了,规则已经讲完了,现在来说一说怎么实现的吧:

首先还是得创建三个文件夹,分别为game.c 游戏需要的具体函数的实现 game.h (所要用的头文件)test.c(游戏的逻辑,菜单,以及函数顺序调用)。

首先看一下test.c:

游戏大概的逻辑就是布置雷,把棋盘打印出来,然后玩家自己扫雷,这部分代码不是很难理解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void game()
{
char mine[ROWS][COLS] = { 0 };//存放布置雷的信息 0无雷 1有雷
char show[ROWS][COLS] = { 0 };//展示给用户看并且存放排查出的雷的信息

InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');

//布置雷
SetMine(mine, ROW, COL);
//打印棋盘
//DisplayBoard(mine, ROW, COL);
DisplayBoard(show, ROW, COL);
//排雷
FindMine(mine,show, ROW, COL);
}
//游戏菜单界面
void menu()
{
printf("************\n");
printf("***1.开始***\n");
printf("***0.退出***\n");
printf("************\n");
}
//选择玩或不玩
void test()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择->;");
scanf_s("%d", &input);
switch (input)
{
case 1:
//扫雷
game();
break;
case 0:
printf("%d\n",input);
printf("即将退出游戏\n");
break;
default:
printf("输入错误,请重新输入:\n");
break;
}
} while (input);
}
int main(void)
{
test();
return 0;
}

接下来是game.h:

          我将所使用到的函数和代码段都写入了代码里应该不难理解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#pragma once
#include<stdio.h>
#include<time.h>
#include<Windows.h>

#define ROW 9//打印出来的棋盘大小
#define COL 9//打印出来的棋盘大小

#define ROWS ROW+2//实际棋盘大小,为了防止越界
#define COLS COL+2//实际棋盘大小,为了防止越界

#define EASY_COUNT 10//简单模式10个雷然后根据自己的需要调整大小

//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
//打印棋盘
void DisplayBoard(char mine[ROWS][COLS], int row, int col);
//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col);
//找雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

 接下来是game.c:

扫雷游戏有一个功能是,点开一个位置,如果周围都没有雷的话就会展开那一片,我们这里用递归来实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//将棋盘展开的函数
void Open(char mine[ROWS][COLS], char show[ROWS][COLS],int x,int y)
{
int n = get_mine_count(mine, x, y);
if (n != 0)
{
show[x][y] = '0' + n;
}
else if (show[x][y] != ' ')
{
show[x][y] = ' ';
int i = 0;
for (i = x - 1; i <= x + 1; i++)
{
int j = 0;
for (j = y - 1; j <= y + 1; j++)
{
Open(mine, show, i, j);
}
}
}
else
{
return;
}
}

完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//初始化棋盘:全部为'*'
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
// 显示应该给用户显示的界面‘*’
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i <= row; i++)
{
printf("%d|", i);
}
printf("\n");
for (i = 0; i < 10; i++)
{
printf("-|");
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d|", i );
for (j = 1; j <= col; j++)
{
printf("%c|", board[i][j]);
}
printf("\n");
for (j = 0; j <col+1; j++)
{
printf("-|");

}
printf("\n");
}
}
void SetMine(char board[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
static int get_mine_count(char mine[ROWS][COLS], int x, int y)
{
return mine[x + 1][y] +
mine[x - 1][y] +
mine[x][y + 1] +
mine[x][y - 1] +
mine[x - 1][y - 1] +
mine[x - 1][y + 1] +
mine[x + 1][y - 1] +
mine[x + 1][y + 1] -
8 * '0';
}
//将棋盘展开的函数
void Open(char mine[ROWS][COLS], char show[ROWS][COLS],int x,int y)
{
int n = get_mine_count(mine, x, y);
if (n != 0)
{
show[x][y] = '0' + n;
}
else if (show[x][y] != ' ')
{
show[x][y] = ' ';
int i = 0;
for (i = x - 1; i <= x + 1; i++)
{
int j = 0;
for (j = y - 1; j <= y + 1; j++)
{
Open(mine, show, i, j);
}
}
}
else
{
return;
}
}
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
while (1)
{
printf("请输入你要查询的坐标->");
scanf("%d%d", &x, &y);
Sleep(500);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if ('1' == mine[x][y])
{
printf("很遗憾,你无了\n");
Sleep(500);
DisplayBoard(mine, row, col);
break;
}
else
{
//计算坐标x,y周围有几个雷
Open(mine,show,x,y);
DisplayBoard(show, row, col);
}
}
else
{
printf("输入坐标非法,无法排雷,请重新输入\n");
}

int i = 0;
int j = 1;
int flag = 0;
for (i = 1; i <= row; i++)
{
for (j = 1; j <= col; j++)
{
if (show[i][j] == '*')
{
flag++;
}
}
}
if (flag == EASY_COUNT)//棋盘全部展开后扫描玩家找的雷的个数是否复合实际雷的个数
{
printf("恭喜你,你赢了!\n");
DisplayBoard(mine, row, col);
break;
}
}


}

由于我要去睡觉了,就先写到这里了,如有需要可以直接拿走,如有不懂的地方可以私信我,我们一起探讨!!!


C语言实现简易版的扫雷游戏
https://6jackjiang.github.io/2021/11/13/categories/C语言/C语言实现简易版的扫雷游戏/
作者
米兰的小铁匠
发布于
2021年11月13日
许可协议