Fork me on GitHub

【C语言】经典小游戏-扫雷


前言

扫雷,是一个Windows平台下一个经典的小游戏,今有兴趣玩了几把后,就利用所学二维数组的相关知识模拟实现了一个“扫雷游戏”。由于学识浅薄,界面有点简陋,尽请谅解!

项目思路:

  • 首先想一想扫雷游戏在Windows平台下是如何实现的。
  • 其次通过观察游戏,我们可以想到需要用两个二维数组来实现扫雷的功能。
  • 游戏刚开始,需要需要显示棋盘,用“*”遮盖雷的坐标,所以要有一个填充棋盘的函数。
  • 通过rand()函数,随机生成雷的坐标,埋雷的函数。
  • 每次扫过后,都要显示新的棋盘,显示棋盘的函数。
  • 如果要想第一次踩不到雷的,需要把该坐标下得雷移动到其他不是雷的坐标,并且点击不是雷,还要满足一点击一片的效果。
  • 最后需要一个函数判断是否扫雷成功。

项目展示:

图片加载

图片加载
是不是很有意思?当然重中之重的是:

要注意需要用二维数组来打印两个棋盘,假如我们要打印10X10的棋盘,那我们的二维数组元素也要为10X10个吗?,不能,因为我们在设计算法时需要统计坐标周围8个方位雷的个数,假如要统计边界坐标周围雷的个数,那么就会有数组越界的问题,那我们就要在10X10的边界多上一圈元素,也就要定义12X12的数组元素,这些元素我们不要打印出来,心里有数就行。

项目源码:

game.h:

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
/*********************************************************************************************
* 项目名称:扫雷游戏 *
* 编译环境:Vs 2013 *
* 创建日期:2018.4.18 *
* 项目编辑:Mr.Yao *
***********************************************************************************************/
//知识点:
//1.数组
//2.函数
//3.循环
//4.扩展内容: 递归 (内存换取时间)

#ifndef __GAME_H_
#define __GAME_H_

#include <stdio.h>
#include <Windows.h>
#include <time.h>
#include <string.h>

enum opp
{
EXIT,
PLAY
};

#define EASY 10
#define HARD 30

#define ROW 10
#define COL 10

#define ROWS (ROW+2)
#define COLS (COL+2)

void InitMap(char arr[ROWS][COLS], int row,int col, char set); //创建初始化棋盘
void PrintMap(char arr[ROWS][COLS], int row, int col); //打印棋盘
void SetMy(char arr[ROWS][COLS], int row, int col, int count); //布雷
void SweepMap(char my_map[ROWS][COLS], char player_map[ROWS][COLS], int row, int cow, int sum); //扫雷
void MoveLei(char my_map[ROWS][COLS], int x, int y); //若第一次扫到雷,则移动雷的位置
void GetCount(char my_map[ROWS][COLS], char player_map[ROWS][COLS], int x, int y);//统计雷数


#endif

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
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#define _CRT_SECURE_NO_WARNINGS 1  

#include "game.h"
//初始化棋盘
void InitMap(char arr[ROWS][COLS], int row, int col, char set)
{
memset(arr, set, col*row*sizeof(arr[0][0]));
}
//打印棋盘
void PrintMap(char arr[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf(" ");
for (i = 1; i<=row ; i++)
{
printf("%3d", i);
}
printf("\n");
for (i = 0; i<=row; i++)
{
printf("---");
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%2d|", i);
for (j = 1; j <= col ; j++)
{
printf("%3c", arr[i][j]);
}
printf("\n");
}

}
//布雷
void SetMy(char arr[ROWS][COLS], int row, int col, int sum)
{
int count = sum;
int x = 0;
int y = 0;
while (count)
{
x = rand() % row + 1;
y = rand() % col + 1;
if (arr[x][y] == '0')
{
arr[x][y] = '1';
count--;
}
}
}
//扫雷
void SweepMap(char my_map[ROWS][COLS],char player_map[ROWS][COLS], int row, int col, int sum)
{
int x = 0;
int y = 0;
int count = 0;
int temp = 0;
int win = 0;

while (win < (row * col - sum))
{
printf("请输入你扫雷坐标:>");
scanf("%d%d", &x, &y);
temp++;
if (x >= 1 && x <= row&&y >= 1 && y <= col)
{

while ((my_map[x][y] == '1') && (temp == 1))
{
//保证玩家第一次不死
MoveLei(my_map, x, y);
//对周围的雷数进行遍历
GetCount(my_map, player_map, x, y);
}

if (my_map[x][y] == '1')
{
printf("\n恭喜你,壮烈牺牲\n");
PrintMap(my_map, ROW, COL);
break;
}
else
{
GetCount(my_map, player_map, x, y);
printf("\n");
win++;
}
PrintMap(player_map, ROW, COL);
}
else
{
printf("坐标输入有误\n");
}

}
if(win == (row * col - sum))
{
printf("恭喜你,排完了\n");
}

}

//若输入的坐标无雷,则要遍历周围,统计雷数
//若周围无雷,则递归遍历,统计周围雷数
void GetCount(char my_map[ROWS][COLS], char player_map[ROWS][COLS], int x, int y)
{


if ((my_map[x][y] == '0'))
{
int count = 0;

if (my_map[x - 1][y - 1] == '1')
count++;

if (my_map[x - 1][y] == '1')
count++;

if (my_map[x - 1][y + 1] == '1')
count++;

if (my_map[x][y - 1] == '1')
count++;

if (my_map[x][y + 1] == '1')
count++;
if (my_map[x + 1][y - 1] == '1')
count++;

if (my_map[x + 1][y] == '1')
count++;

if (my_map[x + 1][y + 1] == '1')
count++;

player_map[x][y] = (count + '0');
}

if (player_map[x][y] == '0')
{
if (player_map[x - 1][y - 1] == '*')
GetCount(my_map, player_map, x - 1, y - 1);

if (player_map[x - 1][y] == '*')
GetCount(my_map, player_map, x - 1, y);

if (player_map[x - 1][y + 1] == '*')
GetCount(my_map, player_map, x - 1, y + 1);

if (player_map[x][y - 1] == '*')
GetCount(my_map, player_map, x, y - 1);

if (player_map[x][y + 1] == '*')
GetCount(my_map, player_map, x, y + 1);

if (player_map[x + 1][y - 1] == '*')
GetCount(my_map, player_map, x + 1, y - 1);

if (player_map[x + 1][y] == '*')
GetCount(my_map, player_map, x + 1, y);

if (player_map[x + 1][y + 1] == '*')
GetCount(my_map, player_map, x + 1, y + 1);
}
}

//为提高游戏体验,设置玩家第一次无论如何都不会被炸死
void MoveLei(char my_map[ROWS][COLS], int x, int y)
{
int ret = 1;
do
{
my_map[x][y] = '0';
while (ret)
{
x = rand() % ROW + 1;
y = rand() % COL + 1;
if (my_map[x][y] == '0')
{
my_map[x][y] = '1';
}
ret--;
}
} while (ret);
}

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
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
#define _CRT_SECURE_NO_WARNINGS 1  


#include "game.h"

void GotoXY(int x, int y) //设定输出位置
{
COORD c;
c.X = x - 1;
c.Y = y - 1;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
}

void meau()
{
GotoXY(10, 5); printf("开始游戏\n Let's Go!");
Sleep(1500);
system("cls");
printf("**** 《扫雷》 ****\n");
printf("************************\n");
printf("******* 1.play *******\n");
printf("******* 0.exit *******\n");
printf("************************\n");
}

void game()
{
int input = 0;
int sum = 0;
char my_map[ROWS][COLS];
char player_map[ROWS][COLS];

InitMap(my_map,ROWS,COLS,'0');
InitMap(player_map, ROWS, COLS, '*');

printf("**** 1.Easy 0.Hard *****\n");
scanf("%d", &input);
switch (input)
{
case PLAY:
sum = EASY;
break;
case EXIT:
sum = HARD;
break;
default:
printf("输入有误\n");
break;
}
printf("\n这个棋盘有%d个雷。\n", sum);
SetMy(my_map,ROW,COL,sum);

PrintMap(player_map, ROW, COL);
//PrintMap(my_map, ROW, COL);
SweepMap(my_map,player_map ,ROW, COL, sum);
system("pause");
}



void test()
{
int input = 0;
do
{
meau();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case PLAY:
game();
break;
case EXIT:
break;
default:
printf("输出有误\n");
}

} while (input);
}

int main()
{
srand((unsigned)time(NULL));
test();
system("pause");
return 0;
}

结语

简单利用C语言做了一个小游戏,如有不正之处,欢迎双击评论!

-------------本文结束感谢您的阅读-------------