C语言实现简单的扫雷小游戏

时间:2022-09-19 13:33:28

本文实例为大家分享了C语言实现扫雷小游戏的具体代码,供大家参考,具体内容如下

在编写扫雷小游戏之前,第一,我们应该列出我们想要实现的扫雷小游戏的功能:

1.显示选中的坐标周围的雷的个数。
2.保证第一次选中的坐标不是雷。
3.选中的坐标周围8个格子中没有雷,则展开。

第二,我们应该明白我们需要两个棋盘来实现扫雷游戏:一个棋盘用来展示给玩家,初始界面全为“ * ” (未翻开的格子),这个页面就是我们常见的扫雷页面。另一个棋盘用来给编写者看,棋盘内只有字符‘1'和字符‘0' 。‘1'代表雷,‘0'代表非雷。使用字符‘1'‘0'来代表雷和非雷有利于我们下一步计算坐标周围雷的个数。

1.初始化棋盘

?
1
2
3
4
5
6
nitboard(show_board, ROWS, COLS,'*'); //‘*'代表未翻开的坐标
 Initboard(mine_board, ROWS, COLS, '0'); //‘0'代表非雷
 void Initboard(char board[ROWS][COLS], int row, int col, char set)
{
 memset(board, set, row*col * sizeof(board[0][0]));
}

2.打印棋盘

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void DisPlayboard(char board[ROWS][COLS], int row, int col)
{
 int i = 0;
 int j = 0;
 printf(" ");
 for (i = 1; 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 ", board[i][j]);
 }
 printf("\n");
 }
 printf("\n");
}

3.在棋盘中埋入雷。(因为每一次重新开始游戏雷的位置不能重复,所以选择用随机数来埋雷)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void GetBoom(char board[ROWS][COLS], int row, int col) //埋雷
{
 int x = 0;
 int y = 0;
 int sum = 0;
 while(1)
 {
 x = rand() % row +1; //雷放在1-9的范围里
 y = rand() % col +1;
 if (1)
 {
 board[x][y] = '1';
 sum++;
 if (sum == M) //埋入雷后跳出循环
 {
 break;
 }
 }
 }

4.确保第一次不踩到雷,如果第一次踩到雷,我们就将此位置改为非雷,然后将此处的雷移动到别处未放置雷的位置。 

(还要考虑一种特殊情况,即如果第一次落子就获得胜利的情况时后面函数就不用再执行了,所以此函数要改为有返回值的函数,这样在调用此函数时就可以判断是否为一次就获得胜利的情况)

?
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
int Judge_first(char mine_board[ROWS][COLS], char show_board[ROWS][COLS], int row, int col)
{
 int x = 0;
 int y = 0;
 int m;
 int n;
 printf("请输入要排查的坐标:");
 scanf("%d%d", &x, &y);
 while (1)
 {
 if (mine_board[x][y] == '1') //如果第一次踩雷,将此坐标改为非雷
 {
 mine_board[x][y] = '0';
 show_board[x][y] = ' ';
 while (1)
 {
 m = rand() % 9 + 1;
 n = rand() % 9 + 1;
 if (m != x && n != y && mine_board[m][n] != '1')
 {
 mine_board[m][n] = '1';
 }
 Open(mine_board, show_board, x, y);
 if (Full(show_board, ROW, COL) == 1) //展开后判断是否一次获得胜利
 {
 printf("游戏胜利\n");
 DisPlayboard(mine_board, ROW, COL);
 return 2;  //一次获得胜利返回2 不再执行PlayerMove函数
 break;
 }
 DisPlayboard(show_board, row, col);
 break;
 }
 break;
 }
 else if (mine_board[x][y] == '0')
 {
 show_board[x][y] = ' ';
 Open(mine_board, show_board, x, y);
 if (Full(show_board, ROW, COL) == 1)
 {
 printf("游戏胜利\n");
 DisPlayboard(mine_board, ROW, COL);
 return 2;
 break;
 }
 DisPlayboard(show_board, row, col);
 break;
 }
 }
}

5.当坐标周围雷个数为0时,展示周围格子,再以X和Y周围八个坐标分别为中心展开,当坐标周围有雷时不再递归展开,并将雷的个数放在该坐标。

?
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
void Open(char mine_board[ROWS][COLS],char show_board[ROWS][COLS], int x, int y)
{
 int ret = 0;
 ret = Num(mine_board, x, y);
 if (ret == 0) //当坐标周围雷个数为0时 打开周围格子 再以X和Y周围八个坐标为中心展开 重复即为递归展开
 {
 show_board[x][y] = ' ';
 if (x - 1 > 0 && y - 1 > 0 && show_board[x - 1][y - 1] == '*')
 {
 Open(mine_board, show_board, x - 1, y - 1);
 }
 if (x - 1 > 0 && y > 0 && show_board[x - 1][y] == '*')
 {
 Open(mine_board, show_board, x - 1, y);
 }
 if (x - 1 > 0 && y + 1 <= COL && show_board[x - 1][y + 1] == '*')
 {
 Open(mine_board, show_board, x - 1, y + 1);
 }
 if (x > 0 && y + 1 <= COL && show_board[x][y + 1] == '*')
 {
 Open(mine_board, show_board, x, y + 1);
 }
 if (x + 1 < ROW && y + 1 <= COL && show_board[x + 1][y + 1] == '*')
 {
 Open(mine_board, show_board, x + 1, y + 1);
 }
 if (x + 1 <= ROW && y > 0 && show_board[x + 1][y] == '*')
 {
 Open(mine_board, show_board, x + 1, y);
 }
 if (x + 1 <= ROW && y - 1 > 0 && show_board[x + 1][y - 1] == '*')
 {
 Open(mine_board, show_board, x + 1, y - 1);
 }
 if (x > 0 && y - 1 > 0 && show_board[x][y - 1] == '*')
 {
 Open(mine_board, show_board, x, y - 1);
 }
 }
 else if (ret != 0)
 show_board[x][y] = Num(mine_board, x, y) + 48;
}

6.计算坐标周围一圈中所含雷的个数。

?
1
2
3
4
5
6
7
8
9
10
int Num(char board[ROWS][COLS], int x, int y)
{
 int sum = 0; //sum为坐标周围雷的个数
 sum = board[x - 1][y - 1]
 + board[x][y - 1] + board[x + 1][y - 1]
 + board[x + 1][y] + board[x + 1][y + 1]
 + board[x][y + 1] + board[x - 1][y + 1]
 + board[x - 1][y] - (8 * '0');
 return sum;
}

7.判断玩家是否排完所有雷。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int Full(char board[ROWS][COLS], int row, int col)
{
 int i;
 int j;
 int sum = 0; //sum为棋盘未翻开格子的个数
 for (i = 1; i <= row; i++)
 {
 for (j = 1; j <= col; j++)
 {
 if (board[i][j] == '*')
 sum++;
 }
 }
 if (sum == M) //当未翻开的格子数为雷数时 返回1
 return 1;
}

8.玩家输入坐标扫雷。

?
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
void PlayerMove(char mine_board[ROWS][COLS], char show_board[ROWS][COLS], int row, int col)
{
 int x = 0;
 int y = 0;
 int ret = 0;
 while (1)
 {
 if (Full(show_board, ROW, COL) == 1) //棋盘未翻开格子等于雷数时玩家胜利
 {
 printf("游戏胜利\n");
 DisPlayboard(mine_board, ROW, COL);
 break;
 }
 printf("请输入坐标:");
 scanf("%d%d", &x, &y);
 if (x >= 1 && x <= row && y >= 1 && y <= col)
 {
 
 if (mine_board[x][y] == '1') //玩家踩到雷,游戏结束
 {
 printf("游戏结束\n");
 DisPlayboard(mine_board, ROW, COL);
 break;
 }
 ret = Num(mine_board, x, y);
 if (ret == 0) //周围没有雷时,展开周围格子
 {
 Open(mine_board, show_board, x, y);
 DisPlayboard(show_board, ROW, COL);
 }
 else if (ret != 0) //周围有雷时打印雷的个数
 {
 show_board[x][y] = ret + 48;
 DisPlayboard(show_board, ROW, COL);
 }
 }
 else
 printf("输入错误,请重新输入");
 }
}

9.函数声明,宏定义,函数的定义实现,测试。

源文件:test.c //主要负责测试整个代码
头文件:game.h //包含函数各种声明,宏定义
源文件:game.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
#include"game.h"
void menu()
{
 printf("************************************\n");
 printf("************************************\n");
 printf("******* 1.play  *******\n");
 printf("******* 0.exit  *******\n");
 printf("************************************\n");
}
 
int game()
{
 char show_board[ROWS][COLS] = { 0 };
 char mine_board[ROWS][COLS] = { 0 };
//
 Initboard(show_board, ROWS, COLS,'*'); //初始化数组
 Initboard(mine_board, ROWS, COLS, '0');
 printf("游戏开始\n");
 DisPlayboard(show_board, ROW, COL); //打印玩家雷盘
//
 GetBoom(mine_board, ROW, COL); //埋雷
 printf("\n\n\n");
 DisPlayboard(mine_board, ROW, COL); //打印雷盘
//
 if (Judge_first(mine_board, show_board, ROW, COL) == 2) //如果一次胜利,就不再执行PlayerMove函数
 return 2;
//
 PlayerMove(mine_board, show_board, ROW, COL);
}
 
void test()
{
 int n;
 menu();
 do
 {
 printf("请输入选项按钮: ");
 scanf("%d", &n);
 switch (n)
 {
 case 1:
 game();
 break;
 case 0:
 printf("游戏退出\n");
 break;
 default:
 printf("输入错误,请重新输入\n");
 break;
 }
 }while(1);
}
int main()
{
 srand((unsigned int)time(NULL));
 test();
}

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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#include"game.h"
void Initboard(char board[ROWS][COLS], int row, int col, char set)
{
 memset(board, set, row*col * sizeof(board[0][0]));
}
void DisPlayboard(char board[ROWS][COLS], int row, int col)
{
 int i = 0;
 int j = 0;
 printf(" ");
 for (i = 1; 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 ", board[i][j]);
 }
 printf("\n");
 }
 printf("\n");
}
 
void GetBoom(char board[ROWS][COLS], int row, int col) //埋雷
{
 int x = 0;
 int y = 0;
 int sum = 0;
 while(1)
 {
 x = rand() % row +1; //雷放在1-9的范围里
 y = rand() % col +1;
 if (1)
 {
 board[x][y] = '1';
 sum++;
 if (sum == M) //埋入所需的雷后跳出循环
 {
 break;
 }
 }
 }
}
 
int Judge_first(char mine_board[ROWS][COLS], char show_board[ROWS][COLS], int row, int col)
{
 int x = 0;
 int y = 0;
 int m;
 int n;
 printf("请输入要排查的坐标:");
 scanf("%d%d", &x, &y);
 while (1)
 {
 if (mine_board[x][y] == '1') //如果第一次踩雷,将此坐标改为非雷
 {
 mine_board[x][y] = '0';
 show_board[x][y] = ' ';
 while (1)
 {
 m = rand() % 9 + 1;
 n = rand() % 9 + 1;
 if (m != x && n != y && mine_board[m][n] != '1')
 {
 mine_board[m][n] = '1';
 }
 Open(mine_board, show_board, x, y);
 if (Full(show_board, ROW, COL) == 1) //展开后判断是否一次获得胜利
 {
 printf("游戏胜利\n");
 DisPlayboard(mine_board, ROW, COL);
 return 2;  //一次获得胜利返回2 不再执行PlayerMove函数
 break;
 }
 DisPlayboard(show_board, row, col);
 break;
 }
 break;
 }
 else if (mine_board[x][y] == '0')
 {
 show_board[x][y] = ' ';
 Open(mine_board, show_board, x, y);
 if (Full(show_board, ROW, COL) == 1)
 {
 printf("游戏胜利\n");
 DisPlayboard(mine_board, ROW, COL);
 return 2;
 break;
 }
 DisPlayboard(show_board, row, col);
 break;
 }
 }
}
 
void PlayerMove(char mine_board[ROWS][COLS], char show_board[ROWS][COLS], int row, int col)
{
 int x = 0;
 int y = 0;
 int ret = 0;
 while (1)
 {
 if (Full(show_board, ROW, COL) == 1) //棋盘下满玩家胜利
 {
 printf("游戏胜利\n");
 DisPlayboard(mine_board, ROW, COL);
 break;
 }
 printf("请输入坐标:");
 scanf("%d%d", &x, &y);
 if (x >= 1 && x <= row && y >= 1 && y <= col)
 {
 
 if (mine_board[x][y] == '1')
 {
 printf("游戏结束\n");
 DisPlayboard(mine_board, ROW, COL);
 break;
 }
 ret = Num(mine_board, x, y);
 if (ret == 0) //周围没有雷时,展开周围格子
 {
 Open(mine_board, show_board, x, y);
 DisPlayboard(show_board, ROW, COL);
 }
 else if (ret != 0) //周围有雷时打印雷的个数
 {
 show_board[x][y] = ret + 48;
 DisPlayboard(show_board, ROW, COL);
 }
 }
 else
 printf("输入错误,请重新输入");
 }
}
 
void Open(char mine_board[ROWS][COLS],char show_board[ROWS][COLS], int x, int y)
{
 int ret = 0;
 ret = Num(mine_board, x, y);
 if (ret == 0) //当坐标周围雷个数为0时 打开周围格子 再以X和Y周围八个坐标为中心展开 重复即为递归展开
 {
 show_board[x][y] = ' ';
 if (x - 1 > 0 && y - 1 > 0 && show_board[x - 1][y - 1] == '*')
 {
 Open(mine_board, show_board, x - 1, y - 1);
 }
 if (x - 1 > 0 && y > 0 && show_board[x - 1][y] == '*')
 {
 Open(mine_board, show_board, x - 1, y);
 }
 if (x - 1 > 0 && y + 1 <= COL && show_board[x - 1][y + 1] == '*')
 {
 Open(mine_board, show_board, x - 1, y + 1);
 }
 if (x > 0 && y + 1 <= COL && show_board[x][y + 1] == '*')
 {
 Open(mine_board, show_board, x, y + 1);
 }
 if (x + 1 < ROW && y + 1 <= COL && show_board[x + 1][y + 1] == '*')
 {
 Open(mine_board, show_board, x + 1, y + 1);
 }
 if (x + 1 <= ROW && y > 0 && show_board[x + 1][y] == '*')
 {
 Open(mine_board, show_board, x + 1, y);
 }
 if (x + 1 <= ROW && y - 1 > 0 && show_board[x + 1][y - 1] == '*')
 {
 Open(mine_board, show_board, x + 1, y - 1);
 }
 if (x > 0 && y - 1 > 0 && show_board[x][y - 1] == '*')
 {
 Open(mine_board, show_board, x, y - 1);
 }
 }
 else if (ret != 0)
 show_board[x][y] = Num(mine_board, x, y) + 48;
}
 
int Num(char board[ROWS][COLS], int x, int y)
{
 int sum = 0;
 sum = board[x - 1][y - 1]
 + board[x][y - 1] + board[x + 1][y - 1]
 + board[x + 1][y] + board[x + 1][y + 1]
 + board[x][y + 1] + board[x - 1][y + 1]
 + board[x - 1][y] - (8 * '0');
 return sum;
}
 
int Full(char board[ROWS][COLS], int row, int col)
{
 int i;
 int j;
 int sum = 0;
 for (i = 1; i <= row; i++)
 {
 for (j = 1; j <= col; j++)
 {
 if (board[i][j] == '*')
 sum++;
 }
 }
 if (sum == M)
 return 1;
}

game.h

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include <stdlib.h>
#include<time.h>
 
#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
#define M 10 //所需雷的个数
 
void test();
int game();
void Initboard(char board[ROWS][COLS], int row, int col, int set); //初始化数组
void DisPlayboard(char board[ROWS][COLS], int row, int col); //打印雷盘
void GetBoom(char board[ROWS][COLS], int row, int col); //安放炸弹
int Judge_first(char mine_board[ROWS][COLS], char show_board[ROWS][COLS], int row, int col); //保证第一次不是雷
void PlayerMove(char mine_board[ROWS][COLS], char show_board[ROWS][COLS], int row, int col); //玩家排雷
void Open(char mine_board[ROWS][COLS],char show_board[ROWS][COLS], int x, int y); //展开函数
int Num(char mine_board[ROWS][COLS], int x, int y); //计算坐标周围雷的数量
int Full(char board[ROWS][COLS], int row, int col); //判断雷是否下满

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/weixin_45177279/article/details/109230071