《扫雷》是一款大众类的益智小游戏,游戏目标是在最短的时间内根据点击格子出现的数字找出所有非雷格子,同时避免踩雷,踩到一个雷即全盘皆输。

这篇博客教大家用C语言制作一个简易版扫雷游戏,和之前的井字棋大同小异。

我们准备三个文件,分别为game.c,test.c,game.h

game.c文件用来写实现游戏功能的各个函数代码,test.c文件写游戏的总流程,game.h文件用来声明函数和初始值.

先看test.c,由menu()``game()``main()三个函数组成。

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
#include"game.h"
menu()
{
printf("--------------------\n");
printf("-----1.开始游戏-----\n");
printf("-----2.退出游戏-----\n");
printf("--------------------\n");
}

game()
{
//棋盘——后台
char mine[ROWS][COLS] = { 0 };
//棋盘——玩家
char show[ROWS][COLS] = { 0 };
//初始化棋盘
init_arr(mine, ROWS, COLS,'0');
init_arr(show, ROWS, COLS, '*');
//打印棋盘
display_arr(show, ROW, COL);
//display_arr(mine, ROW, COL);
//放炸弹
set_mine(mine, ROW, COL);
//排雷
set_coordinate(mine, show, ROW, COL);

}

int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do {
menu();
printf("请输入选项>\n");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 2:
printf("退出游戏\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}

} while (1);
}

下面是game.h头文件,文件内是头文件的引用,数据的初始化,游戏函数的定义

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

#define ROWS 11
#define COLS 11

#define ROW 9
#define COL 9
#define MINE 10

//初始化棋盘
void init_arr(char arr[ROWS][COLS], int rows, int cols,char set);
//打印棋盘
void display_arr(char arr[ROWS][COLS], int row, int col);
//放炸弹
void set_mine(char arr[ROWS][COLS], int row, int col);
//排雷
void set_coordinate(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

我们定义了两个棋盘,一个用来放雷(玩家看不到),一个用来展示玩家选定的位置四周的地雷数。如果是9x9的棋盘,当玩家选择边界位置(如1 1),程序检索其四周的地雷会造成越界访问,所以将棋盘做成11x11,但只打印9x9给玩家。

下面是game.c文件,我们来看下各个函数是如何实现的。

首先是初始化棋盘init_arr

1
2
3
4
5
6
7
8
9
10
void init_arr(char arr[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++) {
arr[i][j] = set;
}
}
}

形参有4个,分别是棋盘,行数,列数,放置的元素。便利整个棋盘,将棋盘初始化。mine棋盘初始化为0,表示不是地雷,1表示地雷;show棋盘初始化为*,展示给玩家。

接着是打印棋盘display_arr

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void display_arr(char arr[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 = 1; i <= row; i++) {
//打印一个行号【行号就是单独的一列】
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", arr[i][j]);
}
printf("\n");
}
}

传入的参数的棋盘,行数,列数,注意这里的行数列数都是9,与初始化不同。为了方便玩家操作,我们在棋盘上标上对应的行数和列数,如下图所示。

image-20220209171309296

接下来布置地雷set_mine

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void set_mine(char arr[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = 0;
while ( count < MINE)
{
x = rand() % row + 1;
y = rand() % col + 1;
if (arr[x][y] == '0') {
arr[x][y] = '1';
count++;
}
}
}

MINE是10,当count<10,生成1-9的随机数,如果坐标位置是0,将该位置置为地雷,count++,直到地雷数为10。

最后是排雷set_coordinate

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
int howmuch_mine(char mine[ROWS][COLS],int x,int y)
{
return mine[x][y + 1] + mine[x - 1][y + 1] + mine[x - 1][y] + mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] - 8 * '0';
}
//排雷
void set_coordinate(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int counts = 0;
while (counts<(ROW*COL-MINE))
{
printf("输入坐标>\n");
scanf("%d %d", &x, &y);
if (x >=1 || x<=col && y >>1 || y<=col)
{
if (show[x][y] == '*') {
if (mine[x][y] == '1') {
printf("很遗憾,你被炸了!\n");
display_arr(mine, ROW, COL);
break;
}
else {
//计算炸弹数
int count = howmuch_mine(mine, x, y);
show[x][y] = count + '0';
display_arr(show, ROW, COL);
counts++;
}
}
else {
printf("坐标已被占用,请重新输入\n");
}
}
else {
printf("坐标非法,请重新输入");
}
}
if (counts == (ROW * COL - MINE)) {
printf("恭喜你,排雷成功\n");
display_arr(mine, ROW, COL);
}
}

输入坐标,判断坐标的合法性,当坐标合法时,如果坐标处是地雷,结束游戏。如果坐标处不是地雷,将show棋盘坐标处的*改成炸弹数,这里需要计算炸弹数,单独写成howmuch_mine函数。函数逻辑是将mine棋盘坐标处四周的元素(8个)相加,无外乎就是字符0或1,再减去8x字符‘0’,这样结果就是地雷个数。

游戏怎样终止呢,排雷成功的条件是什么?9x9的棋盘,10个地雷,理应排71次,将排雷流程写入while语句,定义次数counts,当counts小于71,进入循环,成功排雷1次counts+1,如此往复。跳出while循环后,如果counts为71,排雷成功,打印地雷棋盘mine

大概思路就是这样,一个简单的扫雷游戏就做好了,哪里有错误欢迎评论区指出。