【C 语⾔】贪吃蛇⼩游戏代码详解
贪吃蛇的规则⼤家应该都知道,简单来说就是吃到⾷物则蛇⾝增长,蛇可以在游戏区域内随意移动。游戏结束条件就是蛇撞到边界或者撞到
⾃⼰⾊蛇⾝。
⾸先,实现⼀个函数,这个函数的作⽤是将移动到我们所期望的位置
构建结构体对象
设计这个游戏,最重要的两个对象就是蛇和⾷物,因此⽤两个结构体来代表这两个对象。⾷物只关注其坐标位置,蛇的话,成员包括坐标数组,长度和分数。
初始化游戏边界和⼩蛇/* * 控制光标所在的位置 */void gotoxy (int x , int y ){ COORD coord ; coord .X = x ; coord .Y = y ; SetConsoleCursorPosition (GetStdHandle (STD_OUTPUT_HANDLE ), coord );}
1
2
3
4
5
6
7
8
9
10// 定义游戏区域的边界宽度#define WIDTH 100#define HIGH 20// 定义蛇的最⼤长度#define MAX_LENGHT 100// 定义游戏初始速度#define SPEED 500// 定义游戏中的两个对象:⾷物和蛇struct { int x ; int y ;}food ;struct { int len ; int x_buf [MAX_LENGHT ]; int y_buf [MAX_LENGHT ]; int score ;}snake ;// 要⽤到的全局变量int food_flag = 0;int key = 72;
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
这个没什么难度,就是循环打印,直接放代码。
注意最后⼀⾏使⽤gotoxy函数移动函数很重要,不然光标会在游戏区域内持续闪烁,在退出游戏时,甚⾄会出现显⽰问题。(为了避免遗漏,我基本在每个涉及到光标移动的函数最后都加了这句话)/* * 绘制游戏区域边界 */void DrawMap (void ){ int x , y ; for (x = 0; x < WIDTH + 4; x += 2) { y = 0; gotoxy (x , y ); printf ("■"); y = HIGH + 2; gotoxy (x , y ); printf ("■"); } for (y = 1; y < HIGH + 2; y ++)
{ x = 0; gotoxy (x , y ); printf ("■"); x = WIDTH + 2; gotoxy (x , y ); printf ("■"); } // 将光标移出游戏区域 gotoxy (0, HIGH + 5);}
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
⽣成⾷物
我使⽤⼀个标志位food_flag来代表区域内是否存在⾷物(初始时刻,以及蛇吃到⾷物时,food_flag为0)。当food_flag为0时就执⾏⽣成⾷物的操作。由于要保证游戏的随机性,⽤随机数来⽣成⾷物坐标。/* * 初始化⼩蛇 */void CreateSnake (void ){ int orgin_x , orgin_y ; orgin_x = WIDTH / 2 + 2; orgi
n_y = HIGH / 2 + 1; snake .len = 3; snake .x_buf [0] = orgin_x ; snake .y_buf [0] = orgin_y ; snake .x_buf [1] = orgin_x ; snake .y_buf [1] = ++orgin_y ; snake .x_buf [2] = orgin_x ; snake .y_buf [2] = ++orgin_y ; snake .score = -1; int i ; for (i = 0; i < snake .len ; i ++) { gotoxy (snake .x_buf [i ], snake .y_buf [i ]); printf ("■"); } gotoxy (0, HIGH + 5);}
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
实现的⽅法都⼤同⼩异,但是我强调的点是随机⽣成坐标的实现。由于字符"■"是占两位,所以横坐标必须为2的倍数。其他的帖⼦⾥⼀般是⽤以下⽅法
然后通过while循环来判断x是否适合要求,不符合就重新⽣成。但这种做法会出现⼀种问题,游戏进⾏过程中会出现卡顿的效果。主要原因就是奇偶数出现概率各占50%,因此有⼤概率出现多次的循环
操作。
我的⽅法如下,这样的好处是可以保证⽣成的横坐标⼀定是偶数。避免了⼤量的循环操作。
移动⼩蛇
⾸先要对snake对象中坐标缓存区内的坐标进⾏后移,以便装⼊新的坐标。在此要分两种情况,⼀是⼩蛇没吃到⾷物,则抹去最后⼀节,在头部加⼊新坐标;⼆是⼩蛇吃到⾷物,则不删去最后⼀节。/* * 当游戏区域内不存在⾷物时,随机创造⼀个⾷物 */void CreateFood (void ){ if (food_flag == 0) { int flag = 0,i ; do { srand ((unsigned int )time (NULL )); food .x = (rand () % (WIDTH /2))*2 + 2; food .y = rand () % HIGH + 1; // 判断⽣成的⾷物是否和蛇⾝重合 for (i = 0; i < snake .len ; i ++) { if (snake .x_buf [i ] == food .x && snake .y_buf [i ] == food .y ) { flag = 1; break ; } } } while (flag ); gotoxy (food .x , food .y ); printf ("★"); // 吃到⾷物,则分数加1 snake .score ++; food_flag = 1; } gotoxy (0, HIGH + 5);}
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
36food .x = rand () % WIDTH + 2;food .y = rand () % HIGH + 1;
1
2food .x = (rand () % (WIDTH /2))*2 + 2;food .y = rand () % HIGH + 1;
1
2
随后根据⽤户按键,改变⼩蛇前进⽅向。这块部分代码也是我移植过来的,有详细的注释,就不在这赘述了。void SnakeMove (int x , int y ){ // 判断是否吃到⾷物,吃到长度加1 if (!food_flag ) snake .len ++; // 没吃到则抹去最后⼀节 else { gotoxy (snake .x_buf [snake .len - 1], snake .y_buf [snake .len - 1]); printf (" "); } int i ; for (i = snake .len - 1; i > 0; i --) { snake .x_buf [i ] = snake .x_buf [i - 1]; snake .y_buf [i ] = snake .y_buf [i - 1]; } snake .x_buf [0] = x ; snake .y_buf [0] = y ; gotoxy (snake .x_buf [0], snake .y_buf [0]); printf ("■"); gotoxy (0, HIGH + 5);}
1234567891011121314151617181920212223
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论