7
7
#include < Windows.h>
8
8
9
9
#include " FindPathBFS.h"
10
-
11
10
using namespace std ;
12
11
13
- // ⦾
14
12
int dir[4 ][2 ] = { { 0 ,1 },{ 0 ,-1 },{ 1 ,0 },{ -1 ,0 } };
15
13
16
14
#define UP 1
@@ -20,28 +18,30 @@ int dir[4][2] = { { 0,1 },{ 0,-1 },{ 1,0 },{ -1,0 } };
20
18
#define HEAD 0
21
19
22
20
int speed = 0 ;
23
-
21
+ // 将光标移动到x,y位置
24
22
void gotoxy (int x, int y)
25
23
{
26
24
COORD c;
27
25
c.X = x; c.Y = y;
28
26
SetConsoleCursorPosition (GetStdHandle (STD_OUTPUT_HANDLE), c);
29
27
}
30
-
28
+ // 设置颜色 用到两个Windows API 不做详细介绍
31
29
void setColor (unsigned short ForeColor = 7 , unsigned short BackGroundColor = 0 )
32
30
{
33
31
HANDLE handle = GetStdHandle (STD_OUTPUT_HANDLE);// 获取当前窗口句柄
34
32
SetConsoleTextAttribute (handle, ForeColor + BackGroundColor * 0x10 );// 设置颜色
35
33
}
36
-
34
+ // 游戏设置相关模块,把函数都放到一个类里面了。函数定义为static静态成员,不生成实体也可以直接调用
37
35
class GameSetting
38
36
{
39
37
public:
38
+ // 游戏窗口的长宽
40
39
static const int window_height = 40 ;
41
40
static const int window_width = 80 ;
42
41
public:
43
42
static void GameInit ()
44
43
{
44
+ // 设置游戏窗口大小
45
45
char buffer[32 ];
46
46
sprintf_s (buffer, " mode con cols=%d lines=%d" ,window_width, window_height);
47
47
system (buffer);
@@ -52,15 +52,15 @@ class GameSetting
52
52
GetConsoleCursorInfo (handle, &CursorInfo);// 获取控制台光标信息
53
53
CursorInfo.bVisible = false ; // 隐藏控制台光标
54
54
SetConsoleCursorInfo (handle, &CursorInfo);// 设置控制台光标状态
55
-
55
+ // 初始化随机数种子
56
56
srand ((unsigned int )time (0 ));
57
57
}
58
58
};
59
-
59
+ // 打印信息类,打印相关信息:欢迎,分数,说明,结束等等
60
60
class PrintInfo
61
61
{
62
62
public:
63
-
63
+ // 选择模式:手动? AI?
64
64
static void DrawChoiceInfo ()
65
65
{
66
66
gotoxy (GameSetting::window_width / 2 - 10 , GameSetting::window_height / 2 - 5 );
@@ -72,7 +72,7 @@ class PrintInfo
72
72
gotoxy (GameSetting::window_width / 2 - 10 , GameSetting::window_height / 2 + 1 );
73
73
cout << " 请输入您的选择-> " ;
74
74
}
75
-
75
+ // 画地图边界
76
76
static void DrawMap ()
77
77
{
78
78
system (" cls" );
@@ -104,6 +104,7 @@ class PrintInfo
104
104
cout << " #" ;
105
105
106
106
}
107
+ // 游戏结束
107
108
static void GameOver (int score)
108
109
{
109
110
setColor (12 , 0 );
@@ -112,7 +113,7 @@ class PrintInfo
112
113
gotoxy (GameSetting::window_width / 2 - 20 , GameSetting::window_height / 2 - 3 );
113
114
cout << " 您的得分为:" << score << endl;
114
115
}
115
-
116
+ // 画分数
116
117
static void DrawScore (int score)
117
118
{
118
119
gotoxy (GameSetting::window_width - 22 +14 , 6 );
@@ -126,7 +127,7 @@ class PrintInfo
126
127
cout << " 当前游戏速度: " << 10 - speed / 25 << endl;
127
128
128
129
}
129
-
130
+ // 画游戏操作说明等
130
131
static void DrawGameInfo (bool model)
131
132
{
132
133
gotoxy (GameSetting::window_width - 22 , 8 );
@@ -162,12 +163,12 @@ class PrintInfo
162
163
}
163
164
164
165
};
165
-
166
+ // 食物类,定义食物的生成等相关操作
166
167
class Food
167
168
{
168
169
private:
170
+ // 食物坐标
169
171
COORDINATE m_coordinate;
170
-
171
172
public:
172
173
// 坐标范围:
173
174
// x: 1 to GameSetting::window_width - 30 闭区间
@@ -177,8 +178,10 @@ class Food
177
178
m_coordinate.x = rand () % (GameSetting::window_width - 30 ) + 1 ;
178
179
m_coordinate.y = rand () % (GameSetting::window_height - 2 ) + 1 ;
179
180
unsigned int i;
181
+ // 原则上不允许食物出现在蛇的位置上,如果有,重新生成
180
182
for (i = 0 ; i < coord.size (); i++)
181
183
{
184
+ // 食物出现在蛇身的位置上。重新生成
182
185
if (coord[i].x == m_coordinate.x && coord[i].y == m_coordinate.y )
183
186
{
184
187
m_coordinate.x = rand () % (GameSetting::window_width - 30 ) + 1 ;
@@ -187,49 +190,49 @@ class Food
187
190
}
188
191
}
189
192
}
190
-
193
+ // 默认构造函数
191
194
Food () {}
192
-
195
+ // 构造函数,传入参数为蛇身坐标
193
196
Food (vector<COORDINATE> & coord)
194
197
{
195
198
RandomXY (coord);
196
199
}
197
-
200
+ // 画出食物的位置
198
201
void DrawFood ()
199
202
{
200
203
setColor (12 , 0 );
201
204
gotoxy (m_coordinate.x , m_coordinate.y );
202
205
cout << " @" ;
203
206
setColor (7 , 0 );
204
207
}
205
-
208
+ // 接口,获取食物位置
206
209
COORDINATE GetFoodCoordinate ()
207
210
{
208
211
return m_coordinate;
209
212
}
210
213
211
214
};
212
-
213
-
215
+ // 贪吃蛇类,定义贪吃蛇的移动,打印,吃食物等等
214
216
// 地图范围width:2 to width-2 height: 2 to height-2
215
217
class Snake
216
218
{
217
219
private:
218
220
bool m_model; // true人机 false AI
219
221
int m_direction;
220
222
bool m_is_alive;
223
+ private: // AI功能相关
221
224
bool m_chess[GameSetting::window_width - 29 + 1 ][GameSetting::window_height]; // AI功能用
222
225
FindPathBFS m_AISnake;
223
226
COORDINATE map_size;
224
- public:
227
+ public: // 蛇身坐标
225
228
vector<COORDINATE> m_coordinate;
226
229
227
- public:
230
+ public: // 默认构造函数
228
231
Snake (bool model = false ) : m_model(model) // 默认人机模式
229
232
{
230
233
map_size.x = GameSetting::window_width - 29 + 1 ;
231
234
map_size.y = GameSetting::window_height;
232
-
235
+ // 移动方向向上
233
236
m_direction = 1 ;
234
237
m_is_alive = true ;
235
238
COORDINATE snake_head;
@@ -256,9 +259,9 @@ class Snake
256
259
}
257
260
258
261
}
259
-
262
+ // 设置游戏模式
260
263
void set_model (bool m) { m_model = m; }
261
-
264
+ // 监听键盘
262
265
void listen_key_borad ()
263
266
{
264
267
char ch;
@@ -307,7 +310,7 @@ class Snake
307
310
}
308
311
}
309
312
}
310
-
313
+ // AI功能
311
314
void AI_speed ()
312
315
{
313
316
char ch;
@@ -332,7 +335,7 @@ class Snake
332
335
}
333
336
}
334
337
}
335
-
338
+ // AI功能
336
339
void AI_find_path (Food &f)
337
340
{
338
341
static int not_found = 1 ;
@@ -363,7 +366,7 @@ class Snake
363
366
}
364
367
return false ;
365
368
}
366
-
369
+ // AI功能
367
370
void AI_move_snake ()
368
371
{
369
372
static int cot = 0 ;
@@ -403,14 +406,13 @@ class Snake
403
406
404
407
m_coordinate.insert (m_coordinate.begin (), head);
405
408
}
406
-
409
+ // 移动贪吃蛇
407
410
void move_snake ()
408
411
{
409
-
412
+ // 监听键盘
410
413
listen_key_borad ();
411
-
414
+ // 蛇头
412
415
COORDINATE head = m_coordinate[0 ];
413
-
414
416
// direction方向:1 上 2 下 3 左 4 右
415
417
switch (this ->m_direction )
416
418
{
@@ -427,26 +429,28 @@ class Snake
427
429
head.x ++;
428
430
break ;
429
431
}
430
-
432
+ // 插入移动后新的蛇头
431
433
m_coordinate.insert (m_coordinate.begin (), head);
432
434
}
433
-
435
+ // 判断是否吃到食物
434
436
bool is_eat_food (Food & f)
435
437
{
436
- // TODO
438
+ // 获取食物坐标
437
439
COORDINATE food_coordinate = f.GetFoodCoordinate ();
440
+ // 吃到食物,食物重新生成,不删除蛇尾
438
441
if (m_coordinate[HEAD].x == food_coordinate.x && m_coordinate[HEAD].y == food_coordinate.y )
439
442
{
440
443
f.RandomXY (m_coordinate);
441
444
return true ;
442
445
}
443
446
else
444
447
{
448
+ // 没有吃到食物,删除蛇尾
445
449
m_coordinate.erase (m_coordinate.end () - 1 );
446
450
return false ;
447
451
}
448
452
}
449
-
453
+ // 判断贪吃蛇死了没
450
454
bool snake_is_alive ()
451
455
{
452
456
if (m_coordinate[HEAD].x <= 0 ||
@@ -471,18 +475,20 @@ class Snake
471
475
472
476
return m_is_alive;
473
477
}
474
-
478
+ // 画出贪吃蛇
475
479
void draw_snake ()
476
480
{
481
+ // 设置颜色为浅绿色
477
482
setColor (10 , 0 );
478
483
for (unsigned int i = 0 ; i < this ->m_coordinate .size (); i++)
479
484
{
480
485
gotoxy (m_coordinate[i].x , m_coordinate[i].y );
481
486
cout << " *" ;
482
487
}
488
+ // 恢复原来的颜色
483
489
setColor (7 , 0 );
484
490
}
485
-
491
+ // 清除屏幕上的贪吃蛇
486
492
void ClearSnake ()
487
493
{
488
494
for (unsigned int i = 0 ; i < m_coordinate.size (); i++)
@@ -493,28 +499,27 @@ class Snake
493
499
cout << " " ;
494
500
495
501
}
496
-
502
+ // 获取贪吃蛇的长度
497
503
int GetSnakeSize ()
498
504
{
499
505
return m_coordinate.size ();
500
506
}
501
-
507
+ // 获取当前游戏模式
502
508
bool GetModel ()
503
509
{
504
510
return m_model;
505
511
}
506
-
507
-
508
512
};
509
513
510
-
514
+ // 主函数,组合各种类和资源,进行游戏。
511
515
int main ()
512
516
{
513
517
GameSetting setting;
514
518
PrintInfo print_info;
515
519
Snake snake;
516
-
520
+ // 初始化游戏
517
521
setting.GameInit ();
522
+ // 游戏模式选择
518
523
print_info.DrawChoiceInfo ();
519
524
520
525
char ch = _getch ();
@@ -536,22 +541,23 @@ int main()
536
541
}
537
542
gotoxy (GameSetting::window_width / 2 - 10 , GameSetting::window_height / 2 + 3 );
538
543
system (" pause" );
539
-
544
+ // 画地图
540
545
print_info.DrawMap ();
541
546
print_info.DrawGameInfo (snake.GetModel ());
542
-
547
+ // 生成食物
543
548
Food food (snake.m_coordinate );
544
-
549
+ // 游戏死循环
545
550
while (true )
546
551
{
552
+ // 打印成绩
547
553
print_info.DrawScore (snake.GetSnakeSize ());
548
-
554
+ // 画出食物
549
555
food.DrawFood ();
550
-
556
+ // 清理蛇尾,每次画蛇前必做
551
557
snake.ClearSnake ();
552
-
558
+ // 判断是否吃到食物
553
559
snake.is_eat_food (food);
554
-
560
+ // 根据用户模式选择不同的调度方式
555
561
if (snake.GetModel () == true )
556
562
{
557
563
snake.move_snake ();
@@ -561,19 +567,15 @@ int main()
561
567
snake.AI_find_path (food);
562
568
snake.AI_move_snake ();
563
569
}
564
-
565
-
566
-
570
+ // 画蛇
567
571
snake.draw_snake ();
568
-
569
-
572
+ // 判断蛇是否还活着
570
573
if (!snake.snake_is_alive ())
571
574
{
572
575
print_info.GameOver (snake.GetSnakeSize ());
573
576
break ;
574
577
}
575
-
576
-
578
+ // 控制游戏速度
577
579
Sleep (speed);
578
580
}
579
581
0 commit comments