C语言模拟实现扫雷游戏

时间:2022-12-03 15:18:55

扫雷是Windows系统的经典游戏,下文将利用c语言实现这个经典的小游戏。本版本程序添加了炸弹标记功能。但由于作者水平实现较为死板,此处留坑待以后学习后改进。

Part 1主函数部分:

此部分主要提供用户界面,不同程序均可利用:

?
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
int main()
{
 srand((unsigned int)time(NULL));
 int input = 0;
 do
 {
 menu();
 printf("请选择:>\n");
 scanf("%d", &input);
 switch (input)
 {
 case 1:
  printf("游戏开始!\n");
  game();
  break;
 case 0:
  printf("退出游戏!\n");
  break;
 default:
  printf("输入错误,请重新输入!\n");
  break;
 }
 } while (input);
 return 0;
}

Part 2 函数部分:

我们来思考一下函数的组成:

?
1
2
3
4
5
6
7
8
9
void menu();//实现主函数中菜单
void game();//游戏的核心函数
void InitBoard(char board[ROWS][COLS], int row, int col, char set);//初始化扫雷盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);//可视化扫雷盘
void SetMine(char mine[ROWS][COLS], int row, int col, int count);//设置雷盘
void FindMine(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col, int count);//寻找雷区(用户寻找雷)
int CountMine(char board[ROWS][COLS], int x, int y);//统计周围雷的数量
void show_recusion(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y);//实现点击一下的扩大化应用
int checkwin(char mine[ROWS][COLS], int row, int col);//检查是否获胜

Part 3 整体实现:

?
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
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
#define EASY_COUNT 10
void menu();
void game();
void InitBoard(char board[ROWS][COLS], int row, int col, char set);
void DisplayBoard(char board[ROWS][COLS], int row, int col);
void SetMine(char mine[ROWS][COLS], int row, int col, int count);
void FindMine(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col, int count);
int CountMine(char board[ROWS][COLS], int x, int y);
void show_recusion(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y);
int checkwin(char mine[ROWS][COLS], int row, int col);
int main()
{
 srand((unsigned int)time(NULL));
 int input = 0;
 do
 {
 menu();
 printf("请选择:>\n");
 scanf("%d", &input);
 switch (input)
 {
 case 1:
  printf("游戏开始!\n");
  game();
  break;
 case 0:
  printf("退出游戏!\n");
  break;
 default:
  printf("输入错误,请重新输入!\n");
  break;
 }
 } while (input);
 return 0;
}
void menu()
{
 printf("****************\n");
 printf("*****1.play*****\n");
 printf("*****0.exit*****\n");
 printf("****************\n");
}
void InitBoard(char board[ROWS][COLS], int row, int col, char set)
{
 int i = 0, j = 0;
 for (i = 0; i < row; i++)
 {
 for (j = 0; j < col; j++)
 {
  board[i][j] = set;
 }
 }
}
void DisplayBoard(char board[ROWS][COLS], int row, int col)//打印棋盘时 注意人性化设计便于读取坐标
{
 int i = 0, j = 0;
 printf("-------------扫雷游戏---------------\n");
 for (i = 0; i <= col; 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 SetMine(char mine[ROWS][COLS], int row, int col, int count)
{
 while (count >= 1)
 {
 int x = rand() % row + 1;
 int y = rand() % col + 1;
 if (mine[x][y] == '0')
 {
  mine[x][y] = '1';
  count--;
 }
 }
}
int CountMine(char board[ROWS][COLS], int x, int y)
{
 int i = 0, j = 0;
 int sum = 0;
 for (i = x - 1; i <= x + 1; i++)
 {
 for (j = y - 1; j <= y + 1; j++)
 {
  sum += board[i][j];
 }
 }
 return sum - 9 * '0';//巧妙利用1 0设计,将字符串转化为整型输出
}
void show_recusion(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
 int i = 0, j = 0;
 
 for (i = x - 1; i <= x + 1; i++)
 {
 for (j = y - 1; j <= y + 1; j++)
 {
  if (show[i][j] != ' ' && i >= 1 && i <=ROW && j >= 1 && j <=COL)
  {
  int temp = CountMine(mine, i, j);
  show[i][j] = temp + '0';
  if (show[i][j] == '0')
  {
   show[x][y] = ' ';
   show_recusion(mine, show, i, j);//递归实现扫雷的扩展
  }
  }
 }
 }
}
int checkwin(char show[ROWS][COLS], int row, int col)
{
 int i = 0, j = 0;
 int count = row * col - EASY_COUNT;
 for (i = 1; i <= row; i++)
 {
 for (j = 0; j <= col; j++)
 {
  if (show[i][j] != '*' && show[i][j] != 'B')
  {
  count--;//遍历检查是否全部非雷区已被判断
  }
 }
 }
 if (count == 0)
 {
 return 1;
 }
 else
 {
 return 0;
 }
}
void FindMine(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col, int count) //
{
 while (1)
 {
 int input = 0;
 printf("******1 标记雷区 *****\n");//实现扫雷中的标记功能
 printf("******2 输入坐标 *****\n");//实现扫雷中的输入功能
 scanf("%d", &input);
 if(input==1){
  printf("请输入要选择的坐标:>\n");
  int x, y;
  scanf("%d%d", &x, &y);
  if (x >= 1 && x <= row && y >= 1 && y <= col)
  {
  if (show[x][y] == '*')
  {
   show[x][y] = 'B';
   DisplayBoard(show, ROW, COL);
  }
  else
  {
   printf("非法输入!请重新输入!\n");
  }
  }
  else
  {
  printf("请重新输入!\n");
  }
 }
 else if(input==2)
 {
  printf("请输入要选择的坐标:>\n");
  int x, y;
  scanf("%d%d", &x, &y);
  if (x >= 1 && x <= row && y >= 1 && y <= col)
  {
  if (show[x][y] == '*' || show[x][y]=='B')
  {
   if (mine[x][y] == '1')
   {
   printf("boom!很遗憾您输了!\n");
   break;
   }
   else
   {
   show[x][y] = CountMine(mine, x, y) + '0';
   if (show[x][y] == '0')
   {
    show[x][y] = ' ';
    show_recusion(mine, show, x, y);
   }
   DisplayBoard(show, row, col);
   if (checkwin(show, ROW, COL) == 1)
   {
    printf("恭喜您获胜了!\n");
    break;
   }
   }
  }
  else
  {
   printf("重复输入!请重新输入!\n");
  }
  }
  else
  {
  printf("请重新输入!\n");
  }
 }else{
  printf("输入错误!\n");
 }
 }
}
void game()
 {
 char mine[ROWS][COLS];
 char show[ROWS][COLS];
 InitBoard(mine, ROWS, COLS, '0');
 InitBoard(show, ROWS, COLS, '*');
 // DisplayBoard(mine, ROW, COL); //此处代码为测试用
 DisplayBoard(show, ROW, COL);
 SetMine(mine, ROW, COL, EASY_COUNT);
 // DisplayBoard(mine, ROW, COL); //此处代码为测试用
 // DisplayBoard(show, ROW, COL);//此处代码为测试用
 FindMine(show, mine, ROW, COL, EASY_COUNT);
}

Part 4 总结:

扫雷及三子棋 为C语言数组知识、条件语句、函数知识的综合应用,更多的体现了设计程序的合理性和严谨性,即合理设计搭建函数。相比于五子棋需要更多算法知识,扫雷相对较为容易,但依然有很多细节有待优化。

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

原文链接:https://blog.csdn.net/weixin_54225634/article/details/113132482