C语言 —— 贪吃蛇

参考视频:https://www.bilibili.com/video/av29580072/?p=1

GreedySnake.h

 1 #ifndef GREEDYSNAKE_H_INCLUDED
 2 #define GREEDYSNAKE_H_INCLUDED
 3 
 4 
 5 #define SNAKE_LENGTH 20   //蛇的长度最大为20
 6 #define true  1
 7 #define false 0
 8 enum {UP = -1, DOWN = 1, LEFT = -2, RIGHT = 2};
 9 
10 typedef int bool;
11 
12 void FirstPage();                   //设置起始游戏界面
13 void TestSpace();                   //按空格开始游戏
14 void ShowBackground();              //展示游戏背景
15 void SetSnakeRandPos();             //为蛇产生一个随机的位置
16 void DrawSnake();                   //画蛇
17 void SnakeMove();                   //蛇动
18 void DestroySnake();                //销毁蛇
19 void ChangeDir();                   //蛇随着方向键动起来
20 bool IsSnakeDie();                  //判断蛇是否死亡
21 void ProduceFood();                 //随机位置产生食物
22 void SnakeGrowUp();                 //蛇变长
23 void PrintScore();                  //打印分数
24 
25 
26 #endif // GREEDYSNAKE_H_INCLUDED

GreedySnake.c

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <conio.h>
  5 #include <windows.h>
  6 #include <time.h>
  7 #include "GreedySnake.h"
  8 
  9 //把所有元素置为0
 10 //snake[0][0]表示蛇头的行,snake[0][1]表示蛇头的列,snake[0][2]表示蛇头移动的方向
 11 int snake[SNAKE_LENGTH][3] = { 0 };
 12 
 13 int SnakeLength = 2; //初始长度为3,但数组下标从0开始,故此处为2
 14 
 15 char background[20][50] =
 16 {
 17     "████████████████████████\n",    //一个█占两个字节,占两个字符的位置
 18     "█                                            █\n",
 19     "█                                            █\n",
 20     "█                                            █\n",
 21     "█                                            █\n",
 22     "█                                            █\n",
 23     "█                                            █\n",
 24     "█                                            █\n",
 25     "█                                            █\n",
 26     "█                                            █\n",
 27     "█                                            █\n",
 28     "█                                            █\n",
 29     "█                                            █\n",
 30     "█                                            █\n",
 31     "█                                            █\n",
 32     "█                                            █\n",
 33     "█                                            █\n",
 34     "█                                            █\n",
 35     "█                                            █\n",
 36     "████████████████████████\n"
 37 };
 38 
 39 int SnakeDir = LEFT;     //蛇的方向,默认向左
 40 bool bIsProFood = true;         //蛇产生食物的标记
 41 int row;  //食物的行坐标
 42 int col;  //食物的列坐标
 43 
 44 int score = 0;   //分数
 45 
 46 
 47 
 48 void FirstPage()         //设置起始游戏界面
 49 {
 50     for (int i = 0; i < 20; ++i)
 51         printf(" ");
 52     for (int i = 0; i < 60; ++i)
 53         printf("*");
 54     printf("\n");
 55 
 56     for (int j = 0; j < 5; ++j)
 57     {
 58         for (int i = 0; i < 20; ++i)
 59             printf(" ");
 60         printf("*");
 61         for (int i = 0; i < 58; ++i)
 62             printf(" ");
 63         printf("*\n");
 64     }
 65 
 66     for (int i = 0; i < 20; ++i)
 67         printf(" ");
 68     printf("*");
 69     for (int i = 0; i < 15; ++i)
 70         printf(" ");
 71     printf("《 欢迎来到贪吃蛇的世界!》");
 72     for (int i = 0; i < 16; ++i)
 73         printf(" ");
 74     printf("*\n");
 75 
 76     for (int i = 0; i < 20; ++i)
 77         printf(" ");
 78     printf("*");
 79     for (int i = 0; i < 15; ++i)
 80         printf(" ");
 81     printf("《  请按空格键开始游戏   》");
 82     for (int i = 0; i < 16; ++i)
 83         printf(" ");
 84     printf("*\n");
 85 
 86     for (int j = 0; j < 10; ++j)
 87     {
 88         for (int i = 0; i < 20; ++i)
 89             printf(" ");
 90         printf("*");
 91         for (int i = 0; i < 58; ++i)
 92             printf(" ");
 93         printf("*\n");
 94     }
 95 
 96     for (int i = 0; i < 20; ++i)
 97         printf(" ");
 98     for (int i = 0; i < 60; ++i)
 99         printf("*");
100     for (int i = 0; i < 8; ++i)
101         printf("\n");
102 }
103 
104 void TestSpace()     //按空格开始游戏
105 {
106     char c;
107     while ((c = getch()) != ' ')     //getch()在头文件<conio>内
108     {
109 
110     }
111     system("cls");                  //清屏
112 }
113 
114 void ShowBackground()              //展示游戏背景
115 {
116     for (int i = 0; i < 20; ++i)
117         printf(background[i]);
118 }
119 
120 void SetSnakeRandPos()    //设置蛇的初始位置,默认蛇的身子为三节,向左移动
121 {
122     int x, y;
123     srand((unsigned)time(NULL));
124     x = rand()% 20 + 1;         //因为蛇的身子起始为三节,所以x的范围为1-20(蛇不能起始就撞墙)
125     y = rand()% 18 + 1;
126 
127     snake[0][0] = y;      //行     注意:x,y和初始背景中的行列刚好是反的
128     snake[0][1] = x * 2;  //列     注意:一个█占两个字节,所以算其坐标时要乘以2
129     snake[0][2] = LEFT;   //方向
130 
131     snake[1][0] = y;
132     snake[1][1] = x * 2 + 2;
133     snake[1][2] = LEFT;
134 
135     snake[2][0] = y;
136     snake[2][1] = x * 2 + 4;
137     snake[2][2] = LEFT;
138 
139     DrawSnake();
140 }
141 
142 void DrawSnake()   //展示蛇
143 {
144     //因为一个█占两个字节,所以不能直接用strcpy(&background[snake[i][0]][snake[i][1]],"█");否则会把\0拷贝进来,导致出错
145     //由于前面把snake的所有元素都置为了0,所以当snake[i][0]为0时,代表那个坐标处没有蛇的身子
146     for (int i = 0; snake[i][0] != 0; ++i)
147         strncpy(&background[snake[i][0]][snake[i][1]], "", 2);     //注意取地址符&不能漏掉!
148 }
149 
150 
151 void DestroySnake()                //销毁蛇
152 {
153     for (int i = 0; snake[i][0] != 0; ++i)
154         strncpy(&background[snake[i][0]][snake[i][1]], "  ", 2);       //注意取地址符&不能漏掉!
155 
156 }
157 
158 void SnakeMove()       //蛇动
159 {
160     DestroySnake();
161     for(int i = SNAKE_LENGTH - 1; i >= 1; --i)
162     {
163         if(snake[i][0] != 0)
164         {
165             //把前一个节点的值,赋给当前节点
166             snake[i][0] = snake[i-1][0];
167             snake[i][1] = snake[i-1][1];
168             snake[i][2] = snake[i-1][2];
169         }
170     }
171 
172     snake[0][2] = SnakeDir;     //设置蛇头方向
173 
174     //处理第一个节点(蛇头)
175     if(snake[0][2] == LEFT || snake[0][2] == RIGHT)   //左右移动,列加减2
176     {
177         snake[0][1] += snake[0][2];
178     }
179     else
180     {
181         snake[0][0] += snake[0][2];                   //上下移动,行加减1
182     }
183 
184     DrawSnake();
185 
186 }
187 
188 void ChangeDir()       //改变方向
189 {
190     //不能用getchar(), 会回显,并且要按回车之后才会开始读取
191     //不能用getch(), 同步检测
192 
193     //异步检测
194     if(GetAsyncKeyState('W'))
195     {
196         if (snake[0][2] != DOWN)    //蛇不能回头
197             SnakeDir = UP;
198     }
199 
200     if(GetAsyncKeyState('S'))
201     {
202         if (snake[0][2] != UP)
203             SnakeDir = DOWN;
204     }
205 
206     if(GetAsyncKeyState('A'))
207     {
208         if (snake[0][2] != RIGHT)
209             SnakeDir = LEFT;
210     }
211 
212     if(GetAsyncKeyState('D'))
213     {
214         if (snake[0][2] != LEFT)
215             SnakeDir = RIGHT;
216     }
217 }
218 
219 bool IsSnakeDie()   //蛇死亡判断(包括撞墙和吃自己,两种情况)
220 {
221     if(snake[0][2] == LEFT || snake[0][2] == RIGHT)   //如果蛇左右移动,则判断蛇头的左右是否是"█",如果是,则判定为蛇死亡
222     {
223         if(!strncmp(&background[snake[0][0]][snake[0][1]+snake[0][2]], "", 2))   //注意取地址符&不能漏掉!
224             return true;
225     }
226     else                                              //如果蛇上下移动,则判断蛇头的上下是否是"█"
227     {
228         if(!strncmp(&background[snake[0][0]+snake[0][2]][snake[0][1]], "", 2))
229             return true;
230     }
231     return false;
232 }
233 
234 void ProduceFood()                 //随机位置产生食物
235 {
236     //判断是否产生新的食物
237     if(bIsProFood == false)
238         return;
239 
240     bool flag = true;
241     srand((unsigned)time(NULL));
242 
243     while(1)     //产生合法的食物,即食物不与蛇的身子重合
244     {
245         row = rand()% 18 + 1;   //
246         col = rand()% 22 + 1;
247 
248         for (int i = 0; snake[i][0] != 0; i++)   //遍历蛇
249             if (row == snake[i][0] && col == snake[i][1])       //如果在食物产生在蛇身上
250             {
251                 flag = false;
252                 break;
253             }
254 
255         if(flag == true)
256             break;
257     }
258 
259     strncpy(&background[row][col*2],  "", 2);
260     bIsProFood = false;
261 }
262 
263 void SnakeGrowUp()                 //蛇变长
264 {
265     if(row == snake[0][0] && col*2 == snake[0][1])    //注意:列要乘以2
266     {
267         if (UP == snake[SnakeLength][2])
268         {
269             snake[SnakeLength+1][0] = snake[SnakeLength][0]+1;
270             snake[SnakeLength+1][1] = snake[SnakeLength][0];
271             snake[SnakeLength+1][2] = snake[SnakeLength][2];
272         }
273         else if (DOWN == snake[SnakeLength][2])
274         {
275             snake[SnakeLength+1][0] = snake[SnakeLength][0]-1;
276             snake[SnakeLength+1][1] = snake[SnakeLength][0];
277             snake[SnakeLength+1][2] = snake[SnakeLength][2];
278         }
279         else if (LEFT == snake[SnakeLength][2])
280         {
281             snake[SnakeLength+1][0] = snake[SnakeLength][0];
282             snake[SnakeLength+1][1] = snake[SnakeLength][0]+2;
283             snake[SnakeLength+1][2] = snake[SnakeLength][2];
284         }
285         else if (RIGHT == snake[SnakeLength][2])
286         {
287             snake[SnakeLength+1][0] = snake[SnakeLength][0];
288             snake[SnakeLength+1][1] = snake[SnakeLength][0]-2;
289             snake[SnakeLength+1][2] = snake[SnakeLength][2];
290         }
291         SnakeLength++;
292         bIsProFood = true;
293         score++;
294     }
295 
296 }
297 
298 void PrintScore()                  //打印分数
299 {
300     COORD rd;
301     //设置光标位置
302     rd.X = 59;
303     rd.Y = 10;
304     SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), rd);
305     printf("分数");
306 
307     rd.X = 60;
308     rd.Y = 11;
309     //设置光标位置
310     SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), rd);
311     //打印
312     printf ("%d", score);
313 }

main.c

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <conio.h>
 4 #include <windows.h>
 5 #include <time.h>
 6 #include "GreedySnake.h"
 7 
 8 
 9 int main()
10 {
11     FirstPage();
12     TestSpace();
13     system("cls");
14     SetSnakeRandPos();
15     ShowBackground();
16 
17     while (1)
18     {
19         system("cls");
20         ProduceFood();
21         SnakeGrowUp();
22         ChangeDir();
23 
24         if(IsSnakeDie())
25         {
26             printf("snake die!\n");
27             break;
28         }
29 
30         SnakeMove();
31         ShowBackground();
32         PrintScore();
33 
34         Sleep(500);
35     }
36     system("pause");
37     return 0;
38 }

猜你喜欢

转载自www.cnblogs.com/FengZeng666/p/9694965.html