c語言實現貪吃蛇


游戲分析:

——初期分析

  1. 蛇:考慮到每個蛇節點包含x,y坐標以及指向下一個節點的指針(坐標用c語言內置類型COORD,本質是一個由x和y坐標構成的結構體類型),用結構體類型來表示每一個蛇身節點;
  2. 坐標:c語言有內置的坐標結構體類型,包括x和y坐標,一個坐標對應一個字符的大小,一個方形x方向占兩個字符,即兩個x坐標,y方向占一個;
  3. 光標位置,用一個Pos函數來移動光標到指定位置完成打印輸出;
  4. 生成小蛇;
  5. 隨機出現食物:食物的出現不能超出坐標邊界,使用srand和rand方法生成隨機食物;在生成食物的時候注意由於一開始的x坐標出現在偶數上,所以rand得到的食物的x坐標也必須是偶數,否則蛇吃不到,y坐標沒有限制;
  6. 蛇移動,尋找食物:程序的核心,每次蛇的移動都是在響應一個移動事件,在每兩次移動事件之間加上時間延緩來使蛇的移動看起來自然。當然可以通過加速和減速功能來減小或者增加延緩時間。如果蛇吃到食物,把食物節點作為新的頭節點,后面的節點位置不動。否則把食物作為頭節點,后面的節點依次前移,末尾節點設為空並刷新。
  7. 碰牆,碰自己,用戶返回,游戲結束。

 

 

——幾大模塊

一 ,初始化模塊(init.h):

  功能分析:

      初始化歡迎界面:

                    初始化地圖

                 初始化蛇身

  具體實現:

      初始化歡迎界面:定位好坐標並打印相關歡迎信息即可;

                 初始化地圖:定位好坐標並依次打印出方塊即可;

                初始化蛇身:先生成一個節點,再自左向右依次設置剩下的節點,最后遍歷打印出節點(方塊);

 

二:判斷模塊(judge.h):

    功能分析:

         判斷是否碰牆

                         判斷是否碰到自己

                         判斷游戲是否結束(通過標志位)

     具體實現:

        判斷是否碰牆:如果蛇頭坐標超出地圖范圍,判定為撞牆,修改游戲結束標志位;

        判斷是否碰到自己:從頭部開始遍歷蛇,如果哪個節點坐標和頭部節點坐標重合,就判斷撞到自己;

        判斷游戲是否結束(通過標志位):根據標志位的狀態判斷游戲是否結束;

 

三:游戲模塊(snake.cpp):

            功能分析:

        隨機出現食物

                         玩家操作蛇移動,每次響應一個輸入事件

                         游戲結束

            具體實現:

        隨機出現食物:每次通過rand函數生成一個隨機坐標,把x轉化為偶數坐標,y不變,然后把光標移動到對應位置打印出食物;

        玩家操作蛇移動,每次響應一個鍵盤輸入事件:游戲核心,每次響應移動事件后判斷是否吃到食物:

        1. 吃到食物:把食物節點作為新的頭節點,其余節點位置不變,游戲分數加point;
        2. 沒吃到食物,把新開的后繼節點作為新的頭節點,剩余節點依次向前移動;這樣原來的最后一個節點就成為了空節點,打印出空格來覆蓋原來的方塊。

        游戲結束:結束游戲。

     

代碼如下:

  1 // 定義蛇身節點
  2 typedef struct SNAKE{
  3     int x;
  4     int y;
  5     struct SNAKE*next;
  6 }snake;
  7 snake *head;    //頭指針
  8 //設置光標位置
  9 void Pos(int x, int y)
 10 {
 11     //坐標類型結構體
 12     COORD pos;
 13     pos.X = x;
 14     pos.Y = y;
 15     //定義並初始化句柄
 16     HANDLE Houtput = GetStdHandle(STD_OUTPUT_HANDLE);
 17     //設置光標位置
 18     SetConsoleCursorPosition(Houtput, pos);
 19 }
 20 
 21 void SetColor(int color_num) //需包含頭文件windows.h
 22 {
 23     using namespace std;
 24     HANDLE color; //聲明一個句柄
 25     color = GetStdHandle(STD_OUTPUT_HANDLE); //取得標准輸出句柄
 26     SetConsoleTextAttribute(color, color_num);
 27     //設置顏色函數SetConsoleTextAttribute有兩個參數,第一個為句柄,第二個為顏色代表值 
 28     //可以使用「|」在第二個參數所填顏色間隔開,實現混色
 29 }
 30 
 31 //歡迎界面
 32 void welcomepage()
 33 {
 34     Pos(40, 12);
 35     SetColor(6);
 36     printf("~~歡迎來到貪吃蛇游戲~~");
 37     Pos(40, 25);
 38     printf("用↑,↓,←,→控制蛇的移動\n");
 39     system("pause");
 40     system("cls");
 41 }
 42 //初始化地圖58/2=29列26行
 43 void Map_create()
 44 {
 45     int i;
 46     //■占兩個字符的位置(光標移動一位對應一個字符,兩個字符光標每次移動兩位,也就是坐標值每次加2,一個坐標值對應一個字符位)
 47     //上下 
 48     for (i = 0; i < 58; i += 2)
 49     {
 50         //移動光標
 51         Pos(i, 0);
 52         SetColor(4);
 53         printf("");
 54         Pos(i, 26);
 55         SetColor(6);
 56         printf("");
 57     }
 58     //左右    y取1,2,3...25
 59     for (i = 0; i < 26; i++)
 60     {
 61         //移動光標
 62         Pos(0, i);
 63         SetColor(4);
 64         printf("");
 65         Pos(56, i);
 66         SetColor(6);
 67         printf("");
 68     }
 69     printf("\n");
 70 }
 71 
 72 //初始化蛇身,x,y坐標的取值范圍57和25
 73 void Snakeinit()
 74 {
 75     snake *tail;    //尾指針
 76     int i;
 77     tail = (snake*)malloc(sizeof(snake));    //初始化尾指針,采用頭插法
 78     tail->x = 24;    //這個設定注定頭節點的x坐標只能是偶數
 79     tail->y = 5;    //y坐標任意
 80     tail->next = NULL;
 81     //生成五節長的小蛇
 82     for (i = 1; i <= 4; i++)
 83     {
 84         //生成頭指針,每次將頭指針賦值給尾指針,使蛇增加一節,前面的節已經鏈在了鏈表中
 85         head = (snake*)malloc(sizeof(snake));
 86         head->next = tail;
 87         head->x = 24 + 2 * i;
 88         head->y = 5;
 89         tail = head;
 90     }
 91     //從頭部開始打印小蛇
 92     while (tail != NULL)
 93     {
 94         //修改光標
 95         Pos(tail->x, tail->y);
 96         SetColor(2);
 97         printf("");
 98         tail = tail->next;
 99     }
100 
101 
102 }
init.h

 

 1 int gameoverflag = 0; //游戲分三種情況,1:撞到牆;2:咬到自己;3:主動退出游戲。
 2 int score = 0, point = 10;//總得分與每次吃食物得分。
 3 
 4 int biteself()//判斷是否咬到了自己
 5 {
 6     snake *self;
 7     self = head->next;
 8     while (self != NULL)
 9     {
10         if (self->x == head->x && self->y == head->y)
11         {
12             return 1;
13         }
14         self = self->next;
15     }
16     return 0;
17 }
18 
19 
20 void endgame()//結束游戲
21 {
22 
23     system("cls");
24     Pos(24, 12);
25     if (gameoverflag== 1)
26     {
27         printf("對不起,您撞到牆了。游戲結束.");
28     }
29     else if (gameoverflag == 2)
30     {
31         printf("對不起,您咬到自己了。游戲結束.");
32     }
33     else if (gameoverflag== 3)
34     {
35         printf("您的已經結束了游戲。");
36     }
37     Pos(24, 13);
38     printf("您的得分是%d\n", score);
39     exit(0);
40 }
41 
42 
43 void cantcrosswall()//不能穿牆
44 {
45     if (head->x == 0 || head->x == 56 || head->y == 0 || head->y == 26)
46     {
47         gameoverflag = 1;
48         endgame();
49     }
50 }
51 
52 void game_pause()//暫停
53 {
54     while (1)
55     {
56         Sleep(300);
57         if (GetAsyncKeyState(VK_SPACE))
58         {
59             break;
60         }
61 
62     }
63 }
judge.h

 

  1 #include<stdio.h>
  2 #include<time.h>
  3 #include<windows.h>
  4 #include<stdlib.h>
  5 #include "init.h"
  6 #include "judge.h"
  7 
  8 #define U 1
  9 #define D 2
 10 #define L 3 
 11 #define R 4 //蛇的狀態,U:上 ;D:下;L:左 R:右
 12 
 13 
 14 
 15 //全局變量//
 16 int status, sleeptime = 200;//蛇每次移動的時間間隔200ms
 17 snake *food;//食物指針
 18 snake *q;//遍歷蛇的時候用到的指針
 19 
 20 
 21 
 22 void createfood()//隨機出現食物
 23 {
 24     snake *food_1;
 25     srand((unsigned)time(NULL));
 26     //初始化x坐標
 27     food_1 = (snake*)malloc(sizeof(snake));
 28     while ((food_1->x % 2) != 0) //保證其為偶數,使得食物能與蛇頭對其
 29     {
 30         food_1->x = rand() % 52 + 2;
 31     }
 32     food_1->y = rand() % 24 + 1;
 33     q = head;
 34     while (q->next == NULL)
 35     {
 36         if (q->x == food_1->x && q->y == food_1->y) //判斷蛇身是否與食物重合
 37         {
 38             free(food_1);
 39             createfood();
 40         }
 41         q = q->next;
 42     }
 43     Pos(food_1->x, food_1->y);
 44     food = food_1;
 45     SetColor(4);
 46     printf("");
 47 }
 48 
 49 
 50 
 51 void snakemove()//蛇前進,上U,下D,左L,右R
 52 {
 53     snake * nexthead;
 54     cantcrosswall();
 55 
 56     nexthead = (snake*)malloc(sizeof(snake));
 57     if (status == U)
 58     {
 59         nexthead->x = head->x;
 60         nexthead->y = head->y - 1;
 61         if (nexthead->x == food->x && nexthead->y == food->y)//如果下一個有食物//
 62         {
 63             nexthead->next = head;
 64             head = nexthead;
 65             q = head;
 66             while (q != NULL)
 67             {
 68                 Pos(q->x, q->y);
 69                 SetColor(6);
 70                 printf("");
 71                 q = q->next;
 72             }
 73             score = score + point;
 74             createfood();
 75         }
 76         else //如果沒有食物//
 77         {
 78             nexthead->next = head;
 79             head = nexthead;
 80             q = head;
 81             while (q->next->next != NULL)
 82             {
 83                 Pos(q->x, q->y);
 84                 SetColor(9);
 85                 printf("");
 86                 q = q->next;
 87             }
 88             Pos(q->next->x, q->next->y);
 89             printf(" ");
 90             free(q->next);
 91             q->next = NULL;
 92         }
 93     }
 94     if (status == D)
 95     {
 96         nexthead->x = head->x;
 97         nexthead->y = head->y + 1;
 98         if (nexthead->x == food->x && nexthead->y == food->y) //有食物
 99         {
100             nexthead->next = head;
101             head = nexthead;
102             q = head;
103             while (q != NULL)
104             {
105                 Pos(q->x, q->y);
106                 SetColor(6);
107                 printf("");
108                 q = q->next;
109             }
110             score = score + point;
111             createfood();
112         }
113         else //沒有食物
114         {
115             nexthead->next = head;
116             head = nexthead;
117             q = head;
118             while (q->next->next != NULL)
119             {
120                 Pos(q->x, q->y);
121                 SetColor(12);
122                 printf("");
123                 q = q->next;
124             }
125             Pos(q->next->x, q->next->y);
126             printf(" ");
127             free(q->next);
128             q->next = NULL;
129         }
130     }
131     if (status == L)
132     {
133         nexthead->x = head->x - 2;
134         nexthead->y = head->y;
135         if (nexthead->x == food->x && nexthead->y == food->y)//有食物
136         {
137             nexthead->next = head;
138             head = nexthead;
139             q = head;
140             while (q != NULL)
141             {
142                 Pos(q->x, q->y);
143                 SetColor(6);
144                 printf("");
145                 q = q->next;
146             }
147             score = score + point;
148             createfood();
149         }
150         else //沒有食物
151         {
152             nexthead->next = head;
153             head = nexthead;
154             q = head;
155             while (q->next->next != NULL)
156             {
157                 Pos(q->x, q->y);
158                 SetColor(14);
159                 printf("");
160                 q = q->next;
161             }
162             Pos(q->next->x, q->next->y);
163             printf(" ");
164             free(q->next);
165             q->next = NULL;
166         }
167     }
168     if (status == R)
169     {
170         nexthead->x = head->x + 2;
171         nexthead->y = head->y;
172         if (nexthead->x == food->x && nexthead->y == food->y)//有食物
173         {
174             nexthead->next = head;
175             head = nexthead;
176             q = head;
177             while (q != NULL)
178             {
179                 Pos(q->x, q->y);
180                 SetColor(6);
181                 printf("");
182                 q = q->next;
183             }
184             score = score + point;
185             createfood();
186         }
187         else //沒有食物
188         {
189             nexthead->next = head;
190             head = nexthead;
191             q = head;
192             while (q->next->next != NULL)
193             {
194                 Pos(q->x, q->y);
195                 SetColor(6);
196                 printf("");
197                 q = q->next;
198             }
199             Pos(q->next->x, q->next->y);
200             printf(" ");
201             free(q->next);
202             q->next = NULL;
203         }
204     }
205     if (biteself() == 1) //判斷是否會咬到自己
206     {
207         gameoverflag = 2;
208         endgame();
209     }
210 }
211 
212 
213 //玩游戲
214 void gameplay()
215 {
216 
217     Pos(64, 15);
218     SetColor(6);
219     printf("不能穿牆,不能咬到自己\n");
220     Pos(64, 16);
221     SetColor(7);
222     printf("用↑.↓.←.→分別控制蛇的移動.");
223     Pos(64, 17);
224     SetColor(8);
225     printf("F1 為加速,F2 為減速\n");
226     Pos(64, 18);
227     SetColor(9);
228     printf("ESC :退出游戲.space:暫停游戲.");
229     Pos(64, 20);
230     SetColor(10);
231     printf("~~**~~");
232     status = R;
233     while (1)
234     {
235         Pos(64, 10);
236         printf("得分:%d ", score);
237         Pos(64, 11);
238         printf("每個食物得分:%d分", point);
239         if (GetAsyncKeyState(VK_UP) && status != D)
240         {
241             status = U;
242         }
243         else if (GetAsyncKeyState(VK_DOWN) && status != U)
244         {
245             status = D;
246         }
247         else if (GetAsyncKeyState(VK_LEFT) && status != R)
248         {
249             status = L;
250         }
251         else if (GetAsyncKeyState(VK_RIGHT) && status != L)
252         {
253             status = R;
254         }
255         else if (GetAsyncKeyState(VK_SPACE))
256         {
257             game_pause();
258         }
259         else if (GetAsyncKeyState(VK_ESCAPE))
260         {
261             gameoverflag = 3;
262             endgame();
263         }
264         //加速,就是縮小兩次移動事件之間的響應速度(反應時間)
265         else if (GetAsyncKeyState(VK_F1))
266         {
267             if (sleeptime >= 50)
268             {
269                 //每次減去30ms
270                 sleeptime = sleeptime - 30;
271                 //加速獎勵分,以后吃到食物多加分
272                 point = point + 2;
273             }
274         }
275         //減速,就是增加兩次移動事件之間的響應速度(反應時間)
276         else if (GetAsyncKeyState(VK_F2))
277         {
278             if (sleeptime<350)
279             {
280                 sleeptime = sleeptime + 30;
281                 //減速難度下降,以后吃到食物分減少
282                 point= point- 2;
283                 if (sleeptime == 350)
284                 {
285                     point= 1; //保證最低分為1
286                 }
287             }
288         }
289         //刷新事件,兩次事件之間間隔sleeptime的毫秒
290         Sleep(sleeptime);
291         snakemove();
292     }
293 }
294 
295 
296 
297 void game_init()//游戲初始化
298 {
299     system("mode con cols=100 lines=30");
300     welcomepage();
301     Map_create();
302     Snakeinit();
303     createfood();
304 }
305 
306 int main()
307 {
308     //初始化游戲
309     game_init();
310     //開始玩游戲
311     gameplay();
312     return 0;
313 }
snack.cpp

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM