贪吃蛇小游戏-----C语言实现

1.分析

  众所周知,贪吃蛇游戏是一款经典的益智游戏,有PC和手机等多平台版本,既简单又耐玩。该游戏通过控制蛇头方向吃食物,从而使得蛇变得越来越长,蛇不能撞墙,也不能装到自己,否则游戏结束。玩过贪吃蛇的朋友都知道这个小游戏有一圈“墙”、还有食物以及蛇,还有吃了食物之后的分数。所以通过C语言实现贪吃蛇,可以分为以下几个模块来实现:

  a)编程实现“墙”

  b)实现随机食物的生成

  c)蛇的构建

  d)以上三部分都实现了之后,实现游戏运行的部分,包括蛇的移动、吃食物、判断是否撞墙或者撞到自己。

  e)游戏结束时的相关操作

2.具体思路

  要通过C语言实现贪吃蛇,首先就要用C语言将贪吃蛇的相关信息描述出来。C语言提供了结构体类型,我们可以用结构体描述蛇的结点(结点的横纵坐标)、运动状态、总分数、每个食物的分数等等。

  首先实现进入游戏的"welcome"界面,为了将“欢迎来到贪吃蛇游戏”打印到屏幕的中间,可以运用库函数先设置窗口的大小(system("mode con cols=100 lines=30");将窗口设置为长100,宽30),再通过库函数中的GetStdHandle函数、SetConsoleCursorPosition函数(把光标定位到我们需要的位置)将这句话打印到屏幕中央。

  其次可以通过相同的方法将光标固定到我们需要的位置,用特殊字符‘■’打印实现墙(注意,‘■’在c中占用两个字符,所以在设置循环条件时要格外注意)

扫描二维码关注公众号,回复: 3326875 查看本文章

  接着通过编程实现蛇的移动,本文中蛇是通过单链表实现的,因此在实现蛇的移动时,如果蛇接下来走的位置(上下左右)为食物,将这个位置的用指针表示,可以将食物头插到用_psnake指针维护的蛇身中,如果接下来的位置不是食物,同样头插到蛇身中,再将蛇的最后一个结点打印时输出为空格字符,然后free最后一个节点。

3.代码如下

snake.h:

 1 #pragma once
 2 
 3 #include<Windows.h>
 4 #include<stdio.h>
 5 #include<time.h>
 6 #include<stdlib.h>
 7 
 8 #define WALL "■"
 9 #define FOOD "●"
10 
11 #define INIT_X 20
12 #define INIT_Y 18
13 typedef struct SnakeNode
14 {
15     int x;
16     int y;
17     struct SnakeNode *next;
18 }SnakeNode, *pSnakeNode;
19 
20 //蛇的方向
21 enum Diretion
22 {
23     UP,
24     DOWN,
25     LEFT,
26     RIGHT
27 };
28 
29 //状态
30 enum GameState
31 {
32     OK,
33     NORMAL_END,
34     KILL_BY_WALL,
35     KILL_BY_SELF
36 };
37 //游戏结构体
38 typedef struct Snake
39 {
40     pSnakeNode _psnake;//维护蛇身的指针
41     pSnakeNode _pFood;//维护食物的位置
42     int _TotalScore;//总分数
43     int _AddScore;//增加的分数
44     int _SleepTime;//休眠时间
45     enum Direction  _Dir;
46     enum GameStatus _Status;
47 }Snake, *pSnake;
48 
49 void GameStart(pSnake ps);
50 void WelcomeToGame();//欢迎界面函数
51 void SetPos(int x, int y);
52 void CreateMap();//创建地图
53 void InitSnake(pSnake ps);
54 void CreateFood(pSnake ps);//创建食物
55 void GameRun(pSnake ps);//运行游戏
56 void pause();//暂停函数
57 
58 void snakmove(pSnake ps);
59 int NextHasFood(pSnakeNode pn, pSnakeNode pf);//判断下个结点是否为食物
60 void EatFood(pSnake ps,pSnakeNode pn);//吃食物
61 void NoFood(pSnake ps, pSnakeNode pn);//没有食物
62 void KillBYWALL(pSnake ps);
63 void KillBySelf(pSnake ps);
64 void GameEnd(pSnake ps);

snake.c:

  1 #include"snake.h"
  2 void  SetPos(int x, int y)
  3 {
  4     COORD pos = { 0 };
  5     HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
  6     pos.X = x; pos.Y = y;
  7     SetConsoleCursorPosition(handle, pos);//把光标定位到我们需要的位置了
  8 }
  9 void WelcomeToGame()//欢迎界面函数
 10 {
 11     //设置窗口大小
 12     system("mode con cols=100 lines=30");
 13     SetPos(40, 13);//分装的函数用来定位光标
 14     printf("欢迎来到贪吃蛇小游戏\n");
 15     SetPos(35, 25);
 16     system("pause");//暂停
 17     system("cls");//清空屏幕
 18     SetPos(30, 9);
 19     printf("用↑,↓,←,→来控制蛇的移动,F1为加速,F2为减速\n");
 20     SetPos(40, 11);
 21     printf("加速获得分数更多\n");
 22     SetPos(35, 25);
 23     system("pause");
 24     system("cls");
 25 }
 26 
 27 void CreateMap()
 28 {
 29     int i = 0;
 30     //
 31     for (i = 0; i <= 58; i += 2)
 32     {
 33         SetPos(i, 0);
 34         printf(WALL);
 35     }
 36     //
 37     for (i = 0; i <= 58; i += 2)
 38     {
 39         SetPos(i, 27);
 40         printf(WALL);
 41     }
 42     //
 43     for (i = 1; i <= 26; i++)
 44     {
 45         SetPos(0, i);
 46         printf(WALL);
 47     }
 48     //
 49     for (i = 1; i <= 26; i++)
 50     {
 51         SetPos(58, i);
 52         printf(WALL);
 53     }
 54 }
 55 pSnakeNode BuyNode()
 56 {
 57     pSnakeNode pRet = (pSnakeNode)malloc(sizeof(SnakeNode));
 58     if (pRet == NULL)
 59     {
 60         perror("BuyNode::malloc()");
 61         exit(EXIT_FAILURE);
 62     }
 63     pRet->x = 0;
 64     pRet->y = 0;
 65     pRet->next = NULL;
 66     return pRet;
 67 }
 68 void InitSnake(pSnake ps)
 69 {
 70     pSnakeNode first = BuyNode();//创建蛇头
 71     pSnakeNode cur = NULL;
 72     first->x = INIT_X;
 73     first->y = INIT_Y;
 74     int i = 0;
 75     for (i = 1; i <= 4; i++)
 76     {
 77         cur = BuyNode();//创建蛇身
 78         cur->x = first->x + 2;
 79         cur->y = first->y;
 80         cur->next = first;
 81         first = cur;
 82     }
 83     //打印蛇
 84     while (cur)
 85     {
 86         SetPos(cur->x, cur->y);
 87         printf(FOOD);
 88         cur = cur->next;
 89     }
 90     ps->_psnake = first;
 91 }
 92 
 93 void CreateFood(pSnake ps)
 94 {
 95     pSnakeNode pfood = BuyNode();
 96     pSnakeNode cur = ps->_psnake;
 97     pfood->y = rand() % 26 + 1;
 98     do
 99     {
100         pfood->x = rand() % 55 + 2;//0-54,+2产生2-56
101     } while (pfood->x % 2 != 0);
102     while (cur)
103     {
104         if (cur->x == pfood->x&&cur->y == pfood->y)
105         {
106             CreateFood(ps);
107         }
108         cur = cur->next;
109     }
110     ps->_pFood = pfood;
111     SetPos(pfood->x, pfood->y);
112     printf(FOOD);
113 }
114 
115 void GameStart(pSnake ps)
116 {
117     //打印欢迎界面
118     WelcomeToGame();
119     //创建地图,画墙
120     CreateMap();
121     //初始化蛇
122     InitSnake(ps);
123     //初始化食物
124     CreateFood(ps);
125     //游戏运行
126     ps->_AddScore = 10;//每次增加的分数
127     ps->_TotalScore = 0;//总分
128     ps->_Dir = RIGHT;//方向
129     ps->_SleepTime = 200;//0.2秒
130     ps->_Status = OK;//状态
131 }
132 
133 void pause()//暂停函数
134 {
135     while (1)
136     {
137         Sleep(100);
138         if (GetAsyncKeyState(VK_SPACE))
139         {
140             return;
141         }
142     }
143 }
144 
145 int NextHasFood(pSnakeNode pn, pSnakeNode pf)
146 {
147     return (pn->x == pf->x) && (pn->y == pf->y);
148 }
149 
150 void EatFood(pSnake ps, pSnakeNode pn)//吃食物
151 {
152     pSnakeNode cur = NULL;
153     pn->next = ps->_psnake;//头插
154     ps->_psnake = pn;
155     cur = ps->_psnake;
156     ps->_TotalScore += ps->_AddScore;
157     while (cur)
158     {
159         SetPos(cur->x, cur->y);
160         printf(FOOD);
161         cur = cur->next;
162     }
163     CreateFood(ps);
164 }
165 
166 void NoFood(pSnake ps, pSnakeNode pn)//没有食物
167 {
168     pSnakeNode cur = NULL;
169     pn->next = ps->_psnake;//头插
170     ps->_psnake = pn;
171     cur = ps->_psnake;
172     while (cur->next->next)
173     {
174         SetPos(cur->x, cur->y);
175         printf(FOOD);
176         cur = cur->next;
177     }
178     SetPos(cur->x, cur->y);
179     printf(FOOD);
180     SetPos(cur->next->x, cur->next->y);
181     printf(" ");
182     free(cur->next);
183     cur->next = NULL;
184 }
185 
186 void snakmove(pSnake ps)//蛇的移动
187 {
188     pSnakeNode pNextNode = BuyNode();
189     SetPos(65, 8);
190     printf("总分:%d", ps->_TotalScore);
191     SetPos(65, 9);
192     printf("每个食物的得分:%d ", ps->_AddScore);
193     //
194     switch (ps->_Dir)
195     {
196         case UP:
197         {
198             pNextNode->x = ps->_psnake->x;
199             pNextNode->y = ps->_psnake->y - 1;
200             if (NextHasFood(pNextNode,ps->_pFood))
201             {
202                 //下一个节点是食物
203                 EatFood(ps,pNextNode);
204             }
205             else
206             {
207                 NoFood(ps,pNextNode);
208             }
209             break;
210         }
211         case DOWN:
212         {
213             pNextNode->x = ps->_psnake->x;
214             pNextNode->y = ps->_psnake->y + 1;
215             if (NextHasFood(pNextNode, ps->_pFood))
216             {
217               //下一个节点是食物
218                   EatFood(ps, pNextNode);
219               }
220             else
221             {
222                   NoFood(ps, pNextNode);
223             }
224             break;
225         }
226         case LEFT:
227         {
228             pNextNode->x = ps->_psnake->x-2;
229             pNextNode->y = ps->_psnake->y;
230             if (NextHasFood(pNextNode, ps->_pFood))
231             {
232                 //下一个节点是食物
233                 EatFood(ps, pNextNode);
234             }
235             else
236             {
237                 NoFood(ps, pNextNode);
238             }
239             break;
240         }
241         case RIGHT:
242         {
243             pNextNode->x = ps->_psnake->x+2;
244             pNextNode->y = ps->_psnake->y ;
245             if (NextHasFood(pNextNode, ps->_pFood))
246             {
247                  //下一个节点是食物
248                 EatFood(ps, pNextNode);
249             }
250             else
251             {
252                 NoFood(ps, pNextNode);
253             }
254             break;
255         }
256         default:
257         {
258             break;
259         }
260     }
261 }
262 
263 void KillBYWALL(pSnake ps)
264 {
265     if ((ps->_psnake->x == 0) ||
266         (ps->_psnake->x == 58) || 
267         (ps->_psnake->y == 0) ||
268         (ps->_psnake->y == 27))
269     {
270         ps->_Status = KILL_BY_WALL;
271     }
272 }
273 
274 void KillBySelf(pSnake ps)
275 {
276     pSnakeNode tnext = ps->_psnake->next;
277     while (tnext)
278     {
279         if ((tnext->x == ps->_psnake->x) && (tnext->y == ps->_psnake->y))
280         {
281             ps->_Status = KILL_BY_SELF;
282             return;
283         }
284         tnext = tnext->next;
285     }
286 
287 }
288 void PrintHelpInfo()
289 {
290     SetPos(65, 11);
291     printf("用↑,↓,←,→来控制蛇的移动");
292     SetPos(65, 12);
293     printf("F1为加速,F2为减速\n");
294     SetPos(65, 13);
295     printf("加速获得分数更多\n");
296     SetPos(65, 14);
297     printf("按空格暂停游戏\n");
298 
299 }
300 
301 void GameEnd(pSnake ps)
302 {
303     pSnakeNode cur = ps->_psnake;
304     SetPos(25, 14);
305     if (ps->_Status == NORMAL_END)
306     {
307         SetPos(70, 20);
308         printf("游戏正常接结束\n");
309         SetPos(70, 21);
310     }
311     else if (ps->_Status == KILL_BY_SELF)
312     {
313         SetPos(70, 20);
314         printf("蛇撞到自己了\n");
315         SetPos(70, 21);
316     }
317     else if (ps->_Status == KILL_BY_WALL)
318     {
319         SetPos(70, 20);
320         printf("撞到墙了\n");
321         SetPos(70, 21);
322     }
323     while (cur)
324     {
325         pSnakeNode del = cur;
326         cur = cur->next;
327         free(del);
328         del = NULL;
329     }
330     ps->_psnake = NULL;
331     free(ps->_pFood);
332     ps->_pFood = NULL;
333 }
334 
335 void GameRun(pSnake ps)
336 {
337     PrintHelpInfo();
338     do
339     {
340         //确定方向
341         if (GetAsyncKeyState(VK_UP)&&(ps->_Dir!=DOWN))
342         {
343             ps->_Dir = UP;
344         }
345         else if (GetAsyncKeyState(VK_DOWN) && ps->_Dir != UP)
346         {
347             ps->_Dir = DOWN;
348         }
349         else if (GetAsyncKeyState(VK_LEFT) && ps->_Dir != RIGHT)
350         {
351             ps->_Dir = LEFT;
352         }
353         else if (GetAsyncKeyState(VK_RIGHT) && ps->_Dir != LEFT)
354         {
355             ps->_Dir = RIGHT;
356         }
357         else if (GetAsyncKeyState(VK_SPACE))
358         {
359             //暂停游戏
360             pause();
361         }
362         else if (GetAsyncKeyState(VK_ESCAPE))
363         {
364             //结束游戏
365             ps->_Status = NORMAL_END;
366             break;
367         }
368         else if (GetAsyncKeyState(VK_F1))
369         {
370             //加速
371             if (ps->_SleepTime >= 40)
372             {
373                 ps->_SleepTime -= 20;
374                 ps->_AddScore += 2;
375             }
376         }
377         else if (GetAsyncKeyState(VK_F2))
378         {
379             //减速
380             if (ps->_SleepTime <= 300)
381             {
382                 ps->_SleepTime += 20;
383                 ps->_AddScore -= 2;
384             }
385             if (ps->_SleepTime > 300)
386             {
387                 ps->_AddScore = 1;//不能一直减
388             }
389         }
390         Sleep(ps->_SleepTime);//睡眠
391         //蛇的移动
392         snakmove(ps);
393         KillBYWALL(ps);
394         KillBySelf(ps);
395     } while (ps->_Status == OK);
396 }

test.c:

 1 #include"snake.h"
 2 
 3 void test()
 4 {
 5     srand((unsigned)time(NULL));
 6     Snake snake = { 0 };//创建贪吃蛇
 7     GameStart(&snake);
 8     GameRun(&snake);
 9     GameEnd(&snake);
10 }
11 
12 int main()
13 {
14     test();
15     system("pause");
16     return 0;
17 }

猜你喜欢

转载自www.cnblogs.com/love-you1314/p/9695764.html