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
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
| #include <graphics.h>
#include <stdio.h>
#include <conio.h>
#include <string>
#include <random>
#include <stack>
#include <windows.h>
#include <time.h>
#include <queue>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
#define Windows_x 1100
#define Windows_y 731
#define maze_x 180
#define maze_y 130
MOUSEMSG m;//鼠标对象
struct pos//存储每个格子左上和右下的坐标
{
int x1, y1;
int x2, y2;
} map[30][30];
int maze[30][30] = { 0 };//广搜中的抽象地图
struct node
{
int x, y, s;
} s, e;
int go[4][2] = { { 1,0 },{ -1,0 },{ 0,1 },{ 0,-1 } };
int pre[1000001] = { 0 };
int vis[25][25];
void init();//初始化界面
void start();//游戏逻辑分析
int bfs(int x, int y);//进行广搜
void myprint(int n);//进行打印路径
int bfs(int x, int y)
{
node now, to;
now.x = x, now.y = y, now.s = 0;
queue <node>q;
vis[x][y] = 1;
q.push(now);
while (!q.empty())
{
now = q.front();
q.pop();
if (now.x == e.x&&now.y == e.y)
return now.s;
for (int i = 0; i<4; i++)
{
int xx = now.x + go[i][0];
int yy = now.y + go[i][1];
if (xx >= 0 && xx<20 && yy >= 0 && yy<20 && maze[xx][yy] == 0 && !vis[xx][yy])
{
vis[xx][yy] = 1;
to.x = xx, to.y = yy, to.s = now.s + 1;
pre[xx * 20 + yy] = now.x * 20 + now.y;
q.push(to);
}
}
}
return -1;
}
queue<node>stk;//用队列来存储路径
void myprint(int n)//回溯寻找路径
{
if (-1 == pre[n])return;
myprint(pre[n]);
node t;
t.x = n / 20, t.y = n % 20;
stk.push(t);
}
void start()//开始游戏
{
srand(unsigned(time(0)));//以时间来做随机数种子
loadimage(NULL, "welcome_0.jpg");
setlinestyle(PS_SOLID, 2);//设置划线样式
setlinecolor(BLACK);
rectangle(maze_x, maze_y, maze_x + 500, maze_y + 500);//迷宫的区域
//画出迷宫地图20*20
for (int x = maze_x; x <= maze_x + 500; x += 25)
line(x, maze_y, x, maze_y + 500);
for (int y = maze_y; y <= maze_y + 500; y += 25)
line(maze_x, y, maze_x + 500, y);
//存储每个格子的坐标
for (int i = 0; i<20; i++)
for (int j = 0; j < 20; j++)
{
map[i][j].x1 = maze_x + 25 * j;
map[i][j].y1 = maze_y + 25 * i;
map[i][j].x2 = map[i][j].x1 + 25;
map[i][j].y2 = map[i][j].y1 + 25;
}
//画按钮
setfillcolor(RGB(131, 175, 155));
fillrectangle(700, 130, 950, 634);
rectangle(700, 130, 700 + 250, 130 + 84);//设置起点1
rectangle(700, 130 + 84, 700 + 250, 130 + 84 * 2);//设置终点2
rectangle(700, 130 + 84 * 2, 700 + 250, 130 + 84 * 3);//设置障碍3
rectangle(700, 130 + 84 * 3, 700 + 250, 130 + 84 * 4);//随机障碍4
rectangle(700, 130 + 84 * 4, 700 + 250, 130 + 84 * 5);//开始寻路5
rectangle(700, 130 + 84 * 5, 700 + 250, 130 + 84 * 6);//重置地图6
RECT r1 = { 700, 130, 700 + 250, 130 + 84 };
RECT r2 = { 700, 130 + 84, 700 + 250, 130 + 84 * 2 };
RECT r3 = { 700, 130 + 84 * 2, 700 + 250, 130 + 84 * 3 };
RECT r4 = { 700, 130 + 84 * 3, 700 + 250, 130 + 84 * 4 };
RECT r5 = { 700, 130 + 84 * 4, 700 + 250, 130 + 84 * 5 };
RECT r6 = { 700, 130 + 84 * 5, 700 + 250, 130 + 84 * 6 };
settextcolor(BLUE);
LOGFONT f;
gettextstyle(&f); // 获取当前字体设置
f.lfHeight = 60; // 设置字体高度为 60
_tcscpy(f.lfFaceName, "微软雅黑");
f.lfQuality = ANTIALIASED_QUALITY; // 设置输出效果为抗锯齿
settextstyle(&f); // 设置字体样式
drawtext("设置起点", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("设置终点", &r2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("设置障碍", &r3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("随机障碍", &r4, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("开始寻路", &r5, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("重置游戏", &r6, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
int MODE = 0;//当前按钮所表示的事件
//处理鼠标消息
while (true)
{
BeginBatchDraw();
m = GetMouseMsg();
switch (m.uMsg)
{
case WM_MOUSEMOVE://监测鼠标移动
EndBatchDraw();
if (m.x >= 700 && m.x <= 950 && m.y >= 130 && m.y <= 634)//在按钮区域
{
if (m.y >= 130 && m.y < 214)//设置起点
{
setfillcolor(RGB(254, 67, 101));
fillrectangle(700, 130, 950, 214);//r1
drawtext("设置起点", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
setfillcolor(RGB(131, 175, 155));
fillrectangle(700, 214, 950, 298);//r2
fillrectangle(700, 298, 950, 382);//r3
fillrectangle(700, 382, 950, 466);//r4
fillrectangle(700, 466, 950, 550);//r5
fillrectangle(700, 550, 950, 634);//r6
drawtext("设置终点", &r2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("设置障碍", &r3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("随机障碍", &r4, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("开始寻路", &r5, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("重置游戏", &r6, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
else if (m.y >= 214 && m.y < 298)//设置终点
{
setfillcolor(RGB(254, 67, 101));//r2
fillrectangle(700, 214, 950, 298);
drawtext("设置终点", &r2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
setfillcolor(RGB(131, 175, 155));
fillrectangle(700, 130, 950, 214);//r1
fillrectangle(700, 298, 950, 382);//r3
fillrectangle(700, 382, 950, 466);//r4
fillrectangle(700, 466, 950, 550);//r5
fillrectangle(700, 550, 950, 634);//r6
drawtext("设置起点", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("设置障碍", &r3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("随机障碍", &r4, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("开始寻路", &r5, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("重置游戏", &r6, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
else if (m.y >= 298 && m.y < 382)//设置障碍
{
setfillcolor(RGB(254, 67, 101));
fillrectangle(700, 298, 950, 382);//r3
drawtext("设置障碍", &r3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
setfillcolor(RGB(131, 175, 155));
fillrectangle(700, 130, 950, 214);//r1
fillrectangle(700, 214, 950, 298);//r2
fillrectangle(700, 382, 950, 466);//r4
fillrectangle(700, 466, 950, 550);//r5
fillrectangle(700, 550, 950, 634);//r6
drawtext("设置起点", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("设置终点", &r2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("随机障碍", &r4, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("开始寻路", &r5, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("重置游戏", &r6, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
else if (m.y >= 382 && m.y < 466)//随机障碍
{
setfillcolor(RGB(254, 67, 101));
fillrectangle(700, 382, 950, 466);//r4
drawtext("随机障碍", &r4, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
setfillcolor(RGB(131, 175, 155));
fillrectangle(700, 130, 950, 214);//r1
fillrectangle(700, 214, 950, 298);//r2
fillrectangle(700, 298, 950, 382);//r3
fillrectangle(700, 466, 950, 550);//r5
fillrectangle(700, 550, 950, 634);//r6
drawtext("设置起点", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("设置终点", &r2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("设置障碍", &r3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("开始寻路", &r5, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("重置游戏", &r6, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
else if (m.y >= 466 && m.y < 550)//开始寻路
{
setfillcolor(RGB(254, 67, 101));
fillrectangle(700, 466, 950, 550);//r5
drawtext("开始寻路", &r5, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
setfillcolor(RGB(131, 175, 155));
fillrectangle(700, 130, 950, 214);//r1
fillrectangle(700, 214, 950, 298);//r2
fillrectangle(700, 298, 950, 382);//r3
fillrectangle(700, 382, 950, 466);//r4
fillrectangle(700, 550, 950, 634);//r6
drawtext("设置起点", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("设置终点", &r2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("设置障碍", &r3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("随机障碍", &r4, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("重置游戏", &r6, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
else if (m.y >= 550 && m.y < 634)//重置游戏
{
setfillcolor(RGB(254, 67, 101));
fillrectangle(700, 550, 950, 634);//r6
drawtext("重置游戏", &r6, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
setfillcolor(RGB(131, 175, 155));
fillrectangle(700, 130, 950, 214);//r1
fillrectangle(700, 214, 950, 298);//r2
fillrectangle(700, 298, 950, 382);//r3
fillrectangle(700, 382, 950, 466);//r4
fillrectangle(700, 466, 950, 550);//r5
drawtext("设置起点", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("设置终点", &r2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("设置障碍", &r3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("随机障碍", &r4, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("开始寻路", &r5, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
}
else
{
setfillcolor(RGB(131, 175, 155));
fillrectangle(700, 130, 950, 214);//r1
fillrectangle(700, 214, 950, 298);//r2
fillrectangle(700, 298, 950, 382);//r3
fillrectangle(700, 382, 950, 466);//r4
fillrectangle(700, 466, 950, 550);//r5
fillrectangle(700, 550, 950, 634);//r6
drawtext("设置起点", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("设置终点", &r2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("设置障碍", &r3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("随机障碍", &r4, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("开始寻路", &r5, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawtext("重置游戏", &r6, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
break;
case WM_LBUTTONDOWN://鼠标左键按下
EndBatchDraw();
if (m.x >= 180 && m.x <= 680 && m.y >= 130 && m.y <= 630)//在迷宫区域
{
int tx, ty;//存储抽象坐标
//找到当前点击的点在图上的哪一个坐标
int f = 1;
pos ans;//存储找到的格子
for (int i = 0; i < 20 && f; i++)
{
for (int j = 0; j < 20 && f; j++)
{
if (m.x >= map[i][j].x1&&m.x <= map[i][j].x2&&m.y >= map[i][j].y1&&m.y <= map[i][j].y2)
{
f = 0;
ans = map[i][j];
tx = i, ty = j;
}
}
}
//根据坐标绘图
if (MODE == 1)//起点为红色
{
setfillcolor(RED);
fillrectangle(ans.x1, ans.y1, ans.x2, ans.y2);
s.x = tx, s.y = ty;
MODE = 0;
}
else if (MODE == 2)//终点为蓝色
{
setfillcolor(BLUE);
fillrectangle(ans.x1, ans.y1, ans.x2, ans.y2);
e.x = tx, e.y = ty;
MODE = 0;
}
else if (MODE == 3)//障碍为黑色
{
setfillcolor(BLACK);
fillrectangle(ans.x1, ans.y1, ans.x2, ans.y2);
maze[tx][ty] = 1;
}
}
else if (m.x >= 700 && m.x <= 950 && m.y >= 130 && m.y <= 630)//在按钮区域
{
if (m.y >= 130 && m.y < 214)//设置起点区域
{
MODE = 1;
}
else if (m.y >= 214 && m.y < 298)//设置终点区域
{
MODE = 2;
}
else if (m.y >= 298 && m.y < 382)//设置障碍区域
{
MODE = 3;
}
else if (m.y >= 382 && m.y < 466)//随机障碍区域
{
int rad[30][30];
mem(rad, 0);
for (int cse = 0; cse < 100; cse++)
{
int random_x = rand() % 20;
int random_y = rand() % 20;
if (maze[random_x][random_y] == 0 && rad[random_x][random_y] == 0
&&(random_x!=s.x||random_y!=s.y)&&(random_x!=e.x&&random_y!=e.y))
{
maze[random_x][random_y] = 1;
setfillcolor(BLACK);
pos ans = map[random_x][random_y];
fillrectangle(ans.x1, ans.y1, ans.x2, ans.y2);
}
}
}
else if (m.y >= 466 && m.y < 550)//开始寻路区域,BFS
{
mem(vis, 0);
mem(pre, -1);
int jieguo = bfs(s.x, s.y);
if (jieguo == -1)
{
MessageBox(GetHWnd(), "很遗憾,寻路失败", "提示", 0);
}
else
{
char temp[30];
sprintf(temp, "恭喜,寻路成功,一共%d步!", jieguo);
myprint(e.x * 20 + e.y);
setfillcolor(YELLOW);
while (stk.size() != 1 && !stk.empty())
{
node fr = stk.front();
stk.pop();
Sleep(50);
fillrectangle(map[fr.x][fr.y].x1, map[fr.x][fr.y].y1, map[fr.x][fr.y].x2, map[fr.x][fr.y].y2);
}
MessageBox(GetHWnd(), temp, "提示", 0);
}
}
else if (m.y >= 550 && m.y < 634)//重置游戏区域
{
loadimage(NULL, "welcome_0.jpg");
setlinestyle(PS_SOLID, 2);//设置划线样式
setlinecolor(BLACK);
rectangle(maze_x, maze_y, maze_x + 500, maze_y + 500);//迷宫的区域
//画出迷宫地图20*20
for (int x = maze_x; x <= maze_x + 500; x += 25)
line(x, maze_y, x, maze_y + 500);
for (int y = maze_y; y <= maze_y + 500; y += 25)
line(maze_x, y, maze_x + 500, y);
MODE = 0;
mem(vis, 0);
mem(maze, 0);
mem(pre, -1);
while (!stk.empty())
{
stk.pop();
}
}
}
break;
}
}
_getch(); // 按任意键继续
closegraph(); // 关闭绘图窗口
}
void init()//对开始界面进行渲染
{
initgraph(Windows_x, Windows_y);
loadimage(NULL, "welcome.jpg");
setbkmode(TRANSPARENT);//透明字体
HWND hwnd = GetHWnd();//获取当前窗口句柄
SetWindowText(hwnd, "迷宫自动寻路 --- By:贺鹏程");//设置窗口标题
settextcolor(RGB(77, 77, 77));
LOGFONT f;
gettextstyle(&f); // 获取当前字体设置
f.lfHeight = 65; // 设置字体高度为 48
_tcscpy(f.lfFaceName, "微软雅黑");
f.lfQuality = ANTIALIASED_QUALITY; // 设置输出效果为抗锯齿
settextstyle(&f); // 设置字体样式
RECT BegingameText = { Windows_x / 4 + 100, Windows_y / 2, Windows_x / 4 + 450, Windows_y / 2 + 110 };//"开始游戏"的位置
drawtext("【开 始 游 戏】", &BegingameText, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
bool flag = true;
while (flag)
{
BeginBatchDraw();
m = GetMouseMsg();//获取鼠标消息
switch (m.uMsg)
{
case WM_LBUTTONDOWN://鼠标左键被按下
EndBatchDraw();
if (m.x >= Windows_x / 4 + 100 && m.x <= Windows_x / 4 + 450 && m.y >= Windows_y / 2 && m.y <= Windows_y / 2 + 110)//点击开始游戏
{
flag = false;
start();
}
case WM_MOUSEMOVE://监测鼠标移动
EndBatchDraw();
if (m.x >= Windows_x / 4 + 100 && m.x <= Windows_x / 4 + 450 && m.y >= Windows_y / 2 && m.y <= Windows_y / 2 + 110)
{
settextcolor(RGB(69, 137, 148));
drawtext("【开 始 游 戏】", &BegingameText, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
else
{
settextcolor(RGB(77, 77, 77));
drawtext("【开 始 游 戏】", &BegingameText, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
}
}
}
int main()
{
init();
return 0;
}
|