EasyX实例

EasyX实例

先放代码,讲解后面再来填坑hh

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
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
#include<iostream>
#include<stdlib.h>
#include<graphics.h>
#include<conio.h>
#include<mmsystem.h>
#pragma comment(lib,"winmm.lib")
using namespace std;

//在main函数的while(1)语句中有5个函数,5个bool类型分别控制显示5个页面
bool start = true;
bool intro = false;
bool ask = false;
bool show = false;
bool algo = false;

//判断是否已选择了当前所在地
bool first = true;

//记录当前所在地,目的地
int now;
int to;

//记录将要展示的景点编号
int point;

//歌曲播放和暂停
int play_or_not = 0; //每次点击播放按钮时自动+1,为奇数时暂停播放,为偶数时播放音乐

//景点结构体数组
typedef struct Scenic_Spot{
//outtextxy中只支持char类型的,string类型的不能用
char name[20]; //名字
char rec[100]; //简介
char imgpath[20]; //可以在介绍景点信息时使用,但是有点卡,所以暂时
} Dest;
//用结构体数组来存景点的信息
Dest dest[15];

//相邻两景点的边结构体数组
typedef struct E
{
int value;
//char* p;
} Edge;
Edge e[20][20];

//选项框结构体数组
typedef struct Option_box
{
int left;
int top;
int right;
int down;
} OPb;
//用结构体数组来存选项框的四个坐标信息
OPb opb[15];

//初始化
void init()
{
//初始化名称
strcat_s(dest[0].name, "汇学堂"), strcat_s(dest[0].rec, "各种重大表演活动,报告会,很新很舒适");
//向char数组name中直接写入字符串
strcat_s(dest[1].name, "知行书院"), strcat_s(dest[1].rec, "没去过,应该是个书院");
strcat_s(dest[2].name, "雕塑园"), strcat_s(dest[2].rec, "好多雕塑,很好看");
strcat_s(dest[3].name, "大学生活动中心"), strcat_s(dest[3].rec, "可以弹琴,一二楼很凉快,三楼很热,蚊子多");
strcat_s(dest[4].name, "第六教学楼"), strcat_s(dest[4].rec, "很舒服的学习环境,就是有些小教室蚊子多");
strcat_s(dest[5].name, "大礼堂"), strcat_s(dest[5].rec, "能容纳很多人,形势政策都在那上,但环境不是很好");
strcat_s(dest[6].name, "碧云湖"), strcat_s(dest[6].rec, "没去过,应该是个湖");
strcat_s(dest[7].name, "图书馆"), strcat_s(dest[7].rec, "想要的书都找得到");
strcat_s(dest[8].name, "镜湖"), strcat_s(dest[8].rec, "在西校园,荷花很好看");
strcat_s(dest[9].name, "计电学院"), strcat_s(dest[9].rec, "yyds");
strcat_s(dest[10].name, "外国语学院"), strcat_s(dest[10].rec, "没去过,应该是个学院");
strcat_s(dest[11].name, "邵逸夫楼"), strcat_s(dest[11].rec, "没去过,应该是个楼");
strcat_s(dest[12].name, "西体育馆"), strcat_s(dest[12].rec, "羽毛球上课的地方");
strcat_s(dest[13].name, "东体育馆"), strcat_s(dest[13].rec, "上台球课的时候去过");
strcat_s(dest[14].name, "西26栋"), strcat_s(dest[14].rec, "快跑!");

//边权重的初始化
for (int i = 1; i <= 15; i++)
for (int j = 1; j <= 15; j++)
e[i][j].value = 0;
e[1][1].value = 0, e[1][2].value = 8, e[1][6].value = 21, e[1][9].value = 6;
e[2][1].value = 8, e[2][2].value = 0, e[2][5].value = 13, e[2][9].value = 4, e[2][10].value = 5;
e[3][3].value = 0, e[3][11].value = 11, e[3][15].value = 25;
e[4][4].value = 0, e[4][5].value = 3, e[4][7].value = 18, e[4][15].value = 14;
e[5][2].value = 13, e[5][4].value = 3, e[5][5].value = 0, e[5][13].value = 6;
e[6][1].value = 21, e[6][6].value = 0, e[6][12].value = 5, e[6][14].value = 9;
e[7][4].value = 18, e[7][7].value = 0, e[7][10].value = 6;
e[8][8].value = 0, e[8][10].value = 15;
e[9][1].value = 6, e[9][2].value = 4, e[9][9].value = 0, e[9][12].value = 3, e[9][13].value = 1;
e[10][2].value = 5, e[10][7].value = 6, e[10][8].value = 15, e[10][10].value = 0, e[10][11].value = 4, e[10][14].value = 6;
e[11][3].value = 11, e[11][10].value = 4, e[11][11].value = 0;
e[12][6].value = 5, e[12][9].value = 3, e[12][12].value = 0;
e[13][5].value = 6, e[13][9].value = 1, e[13][13].value = 0;
e[14][6].value = 9, e[14][10].value = 6, e[14][14].value = 0;
e[15][3].value = 25, e[15][4].value = 14, e[15][15].value = 0;
}

//基于Dijkstra算法找出以s为起点,v为终点的单源最短路径
void Algo(int s, int v)
{
//路径查询结果背景
IMAGE img;
loadimage(&img, _T("./5.png"), 640, 480);
putimage(0, 0, &img);

//初始化各变量
int dist[20]; //记录每个节点距离起点的距离
int pre[20]; // 记录该点由哪个路径可达
bool view[20]; //True表示已经确定最短路
int length = 0;
int path[20];

for (int i = 1; i <= 15; i++)
{
dist[i] = 99999; //每个点到s点的距离设为99999
pre[i] = -1; //每个点的前一个点初始化为-1
view[i] = false;
}
dist[s] = 0; //起点距离自己的距离为零 und!
pre[s] = s;

//迭代n次,每次可以确定一个点到起点的最短路
for (int i = 0; i < 15; i++)
{
int t = -1; //初始化标记
for (int j = 1; j <= 15; j++) {
//不在s集合(!view[j]),并且&&
//如果没有更新过(t == -1),则进行更新, 或者发现更短的路径(dist[j] < dist[t]),则进行更新
if (!view[j] && (t == -1 || dist[j] < dist[t])) {
t = j;
}
}

//加入到s集合中
view[t] = true;

//找到了距离最小的点t,并用最小的点t去更新其他的点到起点的距离
for (int j = 1; j <= 15; j++)
{
// dist[j] = min(dist[j], dist[t] + edges[t][j].value);
if (e[t][j].value != 0)
{
if (dist[t] + e[t][j].value < dist[j]) //如果刚找到的点能够更新该点的距离
{
dist[j] = dist[t] + e[t][j].value; //更新距离
pre[j] = t; //更新路径
}
}
}
}

for (int i = v; pre[i] != i; i = pre[i])
{
path[length++] = i;
}
path[length] = s;

settextstyle(30, 0, _T("微软雅黑"));
settextcolor(RGB(0, 205, 0));
outtextxy(0, 20, _T("已为您找到最短路径:"));

settextstyle(30, 0, _T("微软雅黑"));
settextcolor(RGB(0, 205, 0));
int h = 0;
for (int i = length; i >= 0; i--)
{
outtextxy(300, h, dest[path[i] - 1].name);
h += 40;
}

char tmp[5];
snprintf(tmp, sizeof(tmp), "%d" ,dist[v]);
outtextxy(300, h, _T("共需行走:"));
outtextxy(400, h, tmp);
outtextxy(450, h, _T("(公里)"));
//返回按钮
rectangle(520, 410, 620, 470);
rectangle(525, 415, 615, 465);
settextcolor(RGB(80, 96, 109));
settextstyle(40, 10, _T("微软雅黑"));
outtextxy(548, 418, _T("返回"));

//点击返回
MOUSEMSG msg = GetMouseMsg();
if (msg.x >= 520 && msg.x <= 620 && msg.y >= 410 && msg.y <= 470)
{
setfillcolor(RGB(255, 45, 82));
fillrectangle(525, 415, 615, 465);
outtextxy(548, 418, _T("返回"));
if (msg.uMsg == WM_LBUTTONDOWN)
{
ask = true;
algo = false;
}
}
}

//展示景点
void Show()
{
//展示背景
IMAGE img1,img2;
loadimage(&img1, _T("./4.png"), 640, 480);
putimage(0, 0, &img1);

//景点图片,放了太卡,暂时先不放了
//loadimage(&img2, dest[point].imgpath, 400, 300);
//putimage(200, 100, &img2);

//简介内容
settextstyle(40, 0, _T("微软雅黑"));
settextcolor(RGB(238, 0, 0));
outtextxy(50, 20, dest[point].name);
settextcolor(RGB(72, 118, 255));
settextstyle(20, 0, _T("微软雅黑"));
outtextxy(50, 70, _T("简介:"));
outtextxy(90, 70, dest[point].rec);

//返回按钮
rectangle(520, 410, 620, 470);
rectangle(525, 415, 615, 465);
settextcolor(RGB(80, 96, 109));
settextstyle(40, 10, _T("微软雅黑"));
outtextxy(548, 418, _T("返回"));

//点击返回
MOUSEMSG msg = GetMouseMsg();
if (msg.x >= 520 && msg.x <= 620 && msg.y >= 410 && msg.y <= 470)
{
setfillcolor(RGB(255, 45, 82));
fillrectangle(525, 415, 615, 465);
outtextxy(548, 418, _T("返回"));
if (msg.uMsg == WM_LBUTTONDOWN)
{
show = false;
intro = true;
}
}
}

//跳出弹窗询问是否关闭
void end()
{
HWND hnd = GetHWnd();
int isok = MessageBox(hnd, "您确定要退出校园导航吗", "询问", MB_OKCANCEL); //弹窗
if (isok == IDOK)
closegraph();
}

//景点选择
int select()
{
settextstyle(20, 0, _T("微软雅黑"));
setfillcolor(RGB(127, 255, 212));
MOUSEMSG msg = GetMouseMsg();
for (int i = 0; i < 15; i++)
{
if (msg.x >= opb[i].left && msg.x <= opb[i].right && msg.y >= opb[i].top && msg.y <= opb[i].down)
{
fillrectangle(opb[i].left+5, opb[i].top+5, opb[i].right-5, opb[i].down-5);
outtextxy(opb[i].left + 10, opb[i].top + 5, dest[i].name);
if (msg.uMsg == WM_LBUTTONDOWN && intro == true) //因为有两个函数共同调用select,所以要判断一下当前处于的是哪一个页面
{
point = i;
show = true; //在main函数中开启Show界面
intro = false; //在main函数中关闭intro界面
Show();
}
else if (msg.uMsg == WM_LBUTTONDOWN && ask == true)
{
if (first == true)
{
now = i + 1; //迎合算法中的景点编号(我的是从0开始,家弘的是从1开始)
first = false; //说明第一个点已选择
}
else if (first == false)
{
to = i + 1;
ask = false;
algo = true;
//跳转到algo页面,同时main函数中的Algo()通过全局变量now,to来接收两点编号
}
}
}
}
return 0;
}

//景点绘画
void Draw()
{
//大方框线(框内包含所有的景点名)
setlinecolor(RGB(58, 95, 205));
rectangle(200, 50, 630, 400);

int top = 60, down = 100;
int index = 0; //景点编号
//数字选项绘画(五行三列)
for (int i = 0; i < 5; i++)
{
int left = 210, right = 330;
for(int j = 0; j < 3; j++)
{
rectangle(left, top, right, down);
//在绘画景点选项框的同时,记录这些框的四个坐标
opb[index].left = left;
opb[index].top = top;
opb[index].right = right;
opb[index].down = down;
//cout << left << " " << top << " " << right << " " << down << endl;
rectangle(left + 5, top + 5, right - 5, down - 5);
settextcolor(RGB(255, 140, 0));
settextstyle(20, 0, _T("微软雅黑"));
outtextxy(left + 10, top + 5, dest[index].name);
index++;
int width = 120;
left = right + 20, right = left + width;
}
int height = 40;
top = down + 30, down = top + height;
}

}

//景点介绍界面
void Introduce()
{
//咨询背景
IMAGE img;
loadimage(&img, _T("./2.png"), 640, 480);
putimage(0, 0, &img);

//当前标题
setbkmode(TRANSPARENT);
settextcolor(RGB(240, 86, 84));
settextstyle(30, 0, _T("微软雅黑"));
outtextxy(270, 20, _T("请点击您想咨询的景点信息"));

//大方框线及其内容
Draw();

//返回按钮
rectangle(520, 410, 620, 470);
rectangle(525, 415, 615, 465);
settextcolor(RGB(80, 96, 109));
settextstyle(40, 10, _T("微软雅黑"));
outtextxy(548, 418, _T("返回"));

//选择景点,并点击查询
select();

//鼠标点击返回
settextstyle(40, 10, _T("微软雅黑"));
MOUSEMSG msg = GetMouseMsg();
if (msg.x >= 520 && msg.x <= 620 && msg.y >= 410 && msg.y <= 470)
{
setfillcolor(RGB(255, 45, 82));
fillrectangle(525, 415, 615, 465);
outtextxy(548, 418, _T("返回"));
if (msg.uMsg == WM_LBUTTONDOWN)
{
start = true;
intro = false;
}
}

}

//最短路径界面
void Ask()
{
//路径查询背景
IMAGE img;
loadimage(&img, _T("./3.png"), 640, 480);
putimage(0, 0, &img);

//当前标题
setbkmode(TRANSPARENT);
settextcolor(RGB(240, 86, 84));
settextstyle(30, 0, _T("微软雅黑"));
outtextxy(360, 20, _T("景点清单"));

//选择提示
if (first == true)
{
settextcolor(RGB(255, 99, 71));
settextstyle(30, 0, _T("微软雅黑"));
outtextxy(0, 0, _T("请选择您当前所在的位置 :)"));
}
else if(first == false)
{
settextcolor(RGB(255, 99, 71));
settextstyle(30, 0, _T("微软雅黑"));
outtextxy(0, 0, _T("当前位置:"));
settextcolor(RGB(138, 43, 226));
outtextxy(100, 0, dest[now-1].name); //为了和家弘的景点编号对应
settextcolor(RGB(255, 99, 71));
outtextxy(0, 30, _T("请选择您的目的地"));
}

//大方框线及其内容
Draw();

//选择
select();

//返回按钮
rectangle(520, 410, 620, 470);
rectangle(525, 415, 615, 465);
settextcolor(RGB(80, 96, 109));
settextstyle(40, 10, _T("微软雅黑"));
outtextxy(548, 418, _T("返回"));

//点击返回
MOUSEMSG msg = GetMouseMsg();
if (msg.x >= 520 && msg.x <= 620 && msg.y >= 410 && msg.y <= 470)
{
setfillcolor(RGB(255, 45, 82));
fillrectangle(525, 415, 615, 465);
outtextxy(548, 418, _T("返回"));
if (msg.uMsg == WM_LBUTTONDOWN)
{
start = true;
ask = false;
first = true;
}
}
}

//主菜单
void Menu()
{
//菜单背景
IMAGE img;
loadimage(&img, _T("./1.png"), 640, 480);
putimage(0, 0, &img);
//标题
setbkmode(TRANSPARENT);
settextcolor(RGB(240,86,84));
settextstyle(50, 0, _T("微软雅黑"));
//wchar_t wt[] = L"广西大学校园导游咨询";
//outtextxy(200, 20, wt);
outtextxy(200, 20, _T("广西大学校园导游咨询"));

//选项方框
setlinecolor(BLACK);

//退出
rectangle(500, 300, 600, 360);
rectangle(505, 305, 595, 355);

//景点介绍
rectangle(50, 300, 150, 360);
rectangle(55, 305, 145, 355);

//路径查询
rectangle(280, 300, 380, 360);
rectangle(285, 305, 375, 355);

//方框内容
settextcolor(RGB(80, 96, 109));
settextstyle(40, 10, _T("微软雅黑"));
outtextxy(528, 308, _T("退出"));
outtextxy(58, 308, _T("景点咨询"));
outtextxy(286, 308, _T("路径查询"));

//BGM播放窗口
POINT pts[] = { {300,430},{320,445},{300,460} };
polygon(pts, 3);
rectangle(290, 420, 330, 470);


MOUSEMSG msg = GetMouseMsg();

if (msg.x >= 500 && msg.x <= 595 && msg.y >= 300 && msg.y <= 360)
{
setfillcolor(RGB(255,45,82));
fillrectangle(505, 305, 595, 355);
outtextxy(528, 308, _T("退出"));
if (msg.uMsg == WM_LBUTTONDOWN)
{
mciSendString("close bgm", 0, 0, 0);
end();
}
}
else if (msg.x >= 50 && msg.x <= 150 && msg.y >= 300 && msg.y <= 360)
{
setfillcolor(RGB(33, 167, 171));
fillrectangle(55, 305, 145, 355);
outtextxy(58, 308, _T("景点咨询"));
if (msg.uMsg == WM_LBUTTONDOWN)
{
start = false;
intro = true;
}
}
else if (msg.x >= 280 && msg.x <= 380 && msg.y >= 300 && msg.y <= 360)
{
setfillcolor(RGB(254, 241, 67));
fillrectangle(285, 305, 375, 355);
outtextxy(286, 308, _T("路径查询"));
if (msg.uMsg == WM_LBUTTONDOWN)
{
start = false;
ask = true;
}
}
else if(msg.x >= 290 && msg.x <= 330 && msg.y >= 420 && msg.y <= 470)
{
setfillcolor(RGB(0, 204, 221));
fillpolygon(pts, 3);
if (msg.uMsg == WM_LBUTTONDOWN)
{
if (play_or_not % 2 == 0) mciSendString("play bgm", 0, 0, 0);
if (play_or_not % 2 != 0) mciSendString("pause bgm", 0, 0, 0);
play_or_not++;
}
}
}

int main()
{
initgraph(640, 480, EW_SHOWCONSOLE);
HWND hnd = GetHWnd();
SetWindowText(hnd, "活着就是为了樱岛麻衣");
mciSendString("open ./1.wav alias bgm", 0, 0, 0);

init();
while (1)
{
BeginBatchDraw();
cleardevice();
//开始菜单逻辑顺序
if (start)
Menu();
else
{
if (intro)
Introduce();
if (ask)
Ask();
if (show)
Show();
if (algo)
Algo(now, to);
}
EndBatchDraw();
}
_getch();
closegraph();
return 0;
}

本博客所有文章除特别声明外,转载请注明出处!