本文實例為大家分享了C語言表實現貪吃蛇游戲的具體代碼,供大家參考,具體內容如下
總體思想
利用循環鏈表將一條蛇的坐標進行存儲,然后利用gotoxy()函數(可以將光標定位到指定的位置),此時根據蛇的坐標進行輸出“@”,輸出多幾個既可以產生一條蛇。通過遍歷循環鏈表進行蛇的移動,對循環鏈表的插入元素,產生蛇變長的效果。下面為各功能實現的函數
1.貪吃蛇地圖函數map()
2.蛇的移動move(),up(),left()等函數
3.產生食物food()和吃到食物eat_food()
4.蛇吃到食物時產生的變長效果snake_link()函數
5.判斷蛇的死亡,分別為撞墻hit_wall()和自殺suicide()
1.貪吃蛇地圖函數map()
游戲地圖采用的是應該封閉的區域,采用一個數組a[25][50],將此數組初始化為0,將游戲墻的邊緣賦值為1,當數組為0,輸出" ",數組為1,輸出“#”,產生一個地圖。
代碼如下:
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
|
void map() //創建蛇的地圖 { int a[25][50] = {0}; int i,j; for (i = 0; i < 50; i++) { a[0][i] = 1; a[24][i] =1; } for (i = 0; i < 25; i++) { a[i][0] = 1; a[i][49] =1; } for (i = 0; i < 25; i++) for (j = 0; j < 50; j++) { if (j%50 == 0) printf ( "\n" ); if (a[i][j] == 0) { printf ( " " ); } else { printf ( "#" ); } } } |
2.蛇的移動move(),up(),left()等函數
move()函數主要對蛇的上下左右進行更改在此采用switch函數進行解決(下面代碼中ch為全局變量)
代碼如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
void move( struct snake *p) //蛇的移動函數 { while (1) { ch = getch(); switch (ch) { case 'W' :p = up(p); break ; case 'A' :p = left(p); break ; case 'D' :p = right(p); break ; case 'S' :p = down(p); break ; } } } |
讓蛇動起來的即我們主要對蛇的坐標進行更改,此時蛇頭移動一次我們就利用gotoxy()函數進行輸出“@”,然后在蛇尾輸出“ ”,循環往復就可以產生蛇移動的效果,蛇的上下左右則只需在移動一個方向的時候對單一的坐標x或y進行更改,然后對更改的坐標保存進循環鏈表即可。移動函數則主要有up(),left()等,因為做法差不多,在此只對up()函數進行展示
代碼如下
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
|
struct snake *up( struct snake *p) //向上移動 { int x; int y; x = p->pre->x; //將蛇頭坐標賦值給x,y y = p->pre->y; while (p) //對循環鏈表的遍歷,即蛇的遍歷 { Sleep(SNAKE_SPEED); //蛇移動的速度 y--; //向上移動則只需將縱坐標進行減,就可以實現蛇向上移動的效果 gotoxy(p->x,p->y); //定位到蛇尾,輸出“ ”即蛇尾消失 printf ( " " ); gotoxy(x, y); //定位到蛇頭輸出,"@",結合上面的蛇尾消失又進行蛇頭打印,產生蛇移動的效果 printf ( "@" ); suicide(p,x,y); //判斷蛇頭是否撞到蛇身 p = p->next; //將蛇頭的坐標變為下一個 p->pre->x = x; //此時將前一個蛇頭變成蛇尾,通過不斷的遍歷產生不斷移動的效果 p->pre->y = y; food(); //產生食物 eat_food(p,x,y); //判斷是否吃到食物 hit_wall(y); //判斷是否撞墻 if (kbhit()) break ; //判斷是否有按鍵輸入,有就進行蛇移動方向的改變 } return p; } |
3.產生食物food()和吃到食物eat_food()
食物和吃到食物,產生食物則采用了產生隨機數,產生一個食物的x,y坐標分別存放在全局變量food_xy[2]數組里面,最后利用gotoxy(food_xy[0],food_xy[1])隨機產生食物
代碼如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
void food() //產生食物 { int i; if (!flag) //根據flag的值來判斷地圖上是否有食物 { srand ( (unsigned) time ( NULL ) ); for ( i = 0; i < 2; i++ ) //對food_(x,y)來隨機賦值 { food_xy[i] = rand ()%24+2; while (food_xy[0] == 1 || food_xy[0] == 25) //這兩個while為了防止食物 food_xy[0] = rand ()%24+2; //的坐標與地圖的邊緣重疊 while (food_xy[1] >= 49 || food_xy[1] == 1) food_xy[1] = rand ()%24+2; } gotoxy(food_xy[0],food_xy[1]); //打印食物 printf ( "*" ); flag = 1; } } |
吃到食物eat_food(),則我們只需判斷蛇頭是否和食物的坐標重疊,若重疊則表明蛇吃到了食物
代碼如下
1
2
3
4
5
6
7
8
9
10
11
12
|
void eat_food( struct snake *p, int x, int y) //蛇吃到食物,即主要是對蛇頭的x,y坐標和 { //food_xy的坐標進行匹配對比,若相同即調 if (x == food_xy[0] && y == food_xy[1]) //snake_link函數即可 { p = snake_link(p); flag = 0; //表明食物被吃,準備重新產生食物 printSnake(p); gotoxy(8,0); score = score + 1; //得分 printf ( "%d" ,score); } } |
4.蛇吃到食物時產生的變長效果snake_link()函數
蛇的變長,當蛇吃到食物的時候,此時我們將食物的坐標變成蛇頭,然后進行重新的打印蛇,即可以有蛇變成的效果產生,實質為對循環鏈表進行元素的插入。
即通過這樣將食物的坐標插進去循環鏈表,達到蛇變成的效果
代碼如下
1
2
3
4
5
6
7
8
9
10
11
12
|
struct snake *snake_link( struct snake *p) //蛇的連接 { struct snake *q; q = ( struct snake *) malloc ( sizeof ( struct snake)); //即主要是實現了對循環鏈表的插入元素,再 q->x = food_xy[0]; //進行打印蛇,即可有吃到食物蛇變長的結果 q->y = food_xy[1]; q->pre = p->pre; p->pre->next = q; p->pre = q; q->next = p; return p; } |
5.判斷蛇的死亡,分別為撞墻hit_wall()和自殺suicide()
撞墻,則只需判斷蛇頭的單一坐標x軸或者y軸是否與墻壁的坐標是否相等,若相等則說明蛇撞墻了
代碼如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
void hit_wall( int n) //判斷蛇是否撞墻,即對蛇的單一坐標x或者y進行判斷,若等于墻壁的值,即游戲結束 { if (ch == 'W' || ch == 'S' ) if (n == 1 || n == 25) //墻壁的坐標值 { gotoxy(0,26); printf ( "游戲結束!" ); printf ( "你的得分:%d" ,score); exit (0); } if (ch == 'A' || ch == 'D' ) if (n == 0 || n == 49) { gotoxy(0,26); printf ( "游戲結束!" ); printf ( "你的得分:%d" ,score); exit (0); } } |
自殺suicide()即蛇頭是否有撞到了蛇身,做法是把蛇頭的坐標拿出來,與蛇身的坐標進行對比如果相等,說明蛇頭撞到了蛇身,本質上是循環鏈表的值進行匹配,遍歷
代碼如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
void suicide( struct snake *p, int x, int y) //自殺,即撞到自己本身的時候游戲結束 { struct snake *q; //把蛇頭坐標傳遞進來,然后與其自己身體坐標做對比若有相等則表明,蛇頭撞到了蛇身 q = p; while (q != p->next) //即對循環鏈表的遍歷匹配 { if (p->x == x && p->y == y) { gotoxy(0,26); printf ( "游戲結束!" ); printf ( "你的得分:%d" ,score); exit (0); } else p = p->next; } } |
到此蛇的基本功能已經講完,以下是全部代碼。
全部代碼如下
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
|
#include <stdio.h> #include <stdlib.h> #include <windows.h> #include <conio.h> #include <time.h> #define SNAKE_SPEED 200 //蛇移動的速度 int score = 0; //成績得分 int flag = 0; //用于判斷地圖上是否存在食物,0為不存在食物 int food_xy[2]; //定位食物的位置 char ch; //用來決定蛇的移動方向 struct snake //定義一條循環鏈表的蛇 { int x; int y; struct snake *next; struct snake *pre; }; void HideCursor() //把蛇移動的時候產生的光標進行隱藏,隱藏光標函數 { CONSOLE_CURSOR_INFO cursor; cursor.bVisible = FALSE; cursor.dwSize = sizeof (cursor); HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleCursorInfo(handle, &cursor); } void gotoxy( int x, int y) //定位光標函數,用來實現蛇的移動,和食物的出現(傳送x,y可以將光標定位到x,y) { HideCursor(); COORD coord = {x,y}; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord); } void map() //創建蛇的地圖 { int a[25][50] = {0}; int i,j; for (i = 0; i < 50; i++) { a[0][i] = 1; a[24][i] =1; } for (i = 0; i < 25; i++) { a[i][0] = 1; a[i][49] =1; } for (i = 0; i < 25; i++) for (j = 0; j < 50; j++) { if (j%50 == 0) printf ( "\n" ); if (a[i][j] == 0) { printf ( " " ); } else { printf ( "#" ); } } } struct snake *createSnake() //給蛇進行初始化,構建一條蛇,本質為循環鏈表 { int i; struct snake *head,*p,*q; p = q = ( struct snake *) malloc ( sizeof ( struct snake)); head = NULL; head = p; head->pre = NULL; for ( i = 0; i < 5; i++) { p->x = 25 - i; p->y = 13; p->pre = head->pre; head->pre = p; q->next = p; q = p; p = ( struct snake *) malloc ( sizeof ( struct snake)); } q->next = head; return head; } void printSnake( struct snake *p) //打印蛇,利用gotoxy()來對蛇進行打印,只需遍歷一次循環鏈表即可將坐標可視化為一條蛇 { struct snake *q; q = p; while (q != p->next) //循環鏈表的遍歷 { gotoxy(p->x,p->y); //根據坐標和定位光標函數來打@,實現輸出蛇 printf ( "@" ); p = p->next; } gotoxy(p->x,p->y); printf ( "@" ); gotoxy(0,0); printf ( "你的得分:" ); //初始化得分 } void food() //產生食物 { int i; if (!flag) //根據flag的值來判斷地圖上是否有食物 { srand ( (unsigned) time ( NULL ) ); for ( i = 0; i < 2; i++ ) //對food_(x,y)來隨機賦值 { food_xy[i] = rand ()%24+2; while (food_xy[0] == 1 || food_xy[0] == 25) //這兩個while為了防止食物的坐標與地圖的邊緣重疊 food_xy[0] = rand ()%24+2; while (food_xy[1] >= 49 || food_xy[1] == 1) food_xy[1] = rand ()%24+2; } gotoxy(food_xy[0],food_xy[1]); //打印食物 printf ( "*" ); flag = 1; } } struct snake *snake_link( struct snake *p) //蛇的連接 { struct snake *q; q = ( struct snake *) malloc ( sizeof ( struct snake)); //即主要是實現了對循環鏈表的插入元素,再進行打印蛇,即可有吃到食物蛇變長的結果 q->x = food_xy[0]; q->y = food_xy[1]; q->pre = p->pre; p->pre->next = q; p->pre = q; q->next = p; return p; } void eat_food( struct snake *p, int x, int y) //蛇吃到食物,即主要是對蛇頭的x,y坐標和food_xy的坐標進行匹配對比,若相同即調用snake_link函數即可 { if (x == food_xy[0] && y == food_xy[1]) { p = snake_link(p); flag = 0; printSnake(p); gotoxy(8,0); score = score + 1; printf ( "%d" ,score); } } void hit_wall( int n) //判斷蛇是否撞墻,即對蛇的單一坐標x或者y進行判斷,若等于墻壁的值,即游戲結束 { if (ch == 'W' || ch == 'S' ) if (n == 1 || n == 25) { gotoxy(0,26); printf ( "游戲結束!" ); printf ( "你的得分:%d" ,score); exit (0); } if (ch == 'A' || ch == 'D' ) if (n == 0 || n == 49) { gotoxy(0,26); printf ( "游戲結束!" ); printf ( "你的得分:%d" ,score); exit (0); } } void suicide( struct snake *p, int x, int y) //自殺,即撞到自己本身的時候游戲結束 { struct snake *q; //把蛇頭坐標傳遞進來,然后與其自己身體坐標做對比若有相等則表明,蛇頭撞到了蛇身 q = p; while (q != p->next) //即對循環鏈表的遍歷匹配 { if (p->x == x && p->y == y) { gotoxy(0,26); printf ( "游戲結束!" ); printf ( "你的得分:%d" ,score); exit (0); } else p = p->next; } } struct snake *up( struct snake *p) //向上移動 { int x; int y; x = p->pre->x; //將蛇頭坐標賦值給x,y y = p->pre->y; while (p) //對循環鏈表的遍歷,即蛇的遍歷 { Sleep(SNAKE_SPEED); //蛇移動的速度 y--; //向上移動則只需將縱坐標進行減,就可以實現蛇向上移動的效果 gotoxy(p->x,p->y); //定位到蛇尾,輸出“ ”即蛇尾消失 printf ( " " ); gotoxy(x, y); //定位到蛇頭輸出,"@",結合上面的蛇尾消失又進行蛇頭打印,產生蛇移動的效果 printf ( "@" ); suicide(p,x,y); //判斷蛇頭是否撞到蛇身 p = p->next; //將蛇頭的坐標變為下一個 p->pre->x = x; //此時將前一個蛇頭變成蛇尾,通過不斷的遍歷產生不斷移動的效果 p->pre->y = y; food(); //產生食物 eat_food(p,x,y); //判斷是否吃到食物 hit_wall(y); //判斷是否撞墻 if (kbhit()) break ; //判斷是否有按鍵輸入,有就進行蛇移動方向的改變 } return p; } struct snake *left( struct snake *p) //向左移動 { int x; int y; x = p->pre->x; y = p->pre->y; while (p) { Sleep(SNAKE_SPEED); x--; gotoxy(p->x,p->y); printf ( " " ); gotoxy(x, y); printf ( "@" ); suicide(p,x,y); p = p->next; p->pre->x = x; p->pre->y = y; food(); eat_food(p,x,y); hit_wall(x); if (kbhit()) break ; } return p; } struct snake *down( struct snake *p) //向下移動 { int x; int y; x = p->pre->x; y = p->pre->y; while (p) { Sleep(SNAKE_SPEED); y++; gotoxy(p->x,p->y); printf ( " " ); gotoxy(x, y); printf ( "@" ); suicide(p,x,y); p = p->next; p->pre->x = x; p->pre->y = y; food(); eat_food(p,x,y); hit_wall(y); if (kbhit()) break ; } return p; } struct snake *right( struct snake *p) //向右移動 { int x; int y; x = p->pre->x; y = p->pre->y; while (p) { Sleep(SNAKE_SPEED); x++; gotoxy(p->x,p->y); printf ( " " ); gotoxy(x, y); printf ( "@" ); suicide(p,x,y); p = p->next; p->pre->x = x; p->pre->y = y; food(); eat_food(p,x,y); hit_wall(x); if (kbhit()) break ; } return p; } void move( struct snake *p) //蛇的移動函數 { while (1) { ch = getch(); switch (ch) { case 'W' :p = up(p); break ; case 'A' :p = left(p); break ; case 'D' :p = right(p); break ; case 'S' :p = down(p); break ; } } } int main() { struct snake *p; map(); //產生地圖 p = createSnake(); // 初始化蛇 printSnake(p); // 打印蛇 move(p); //移動蛇 return 0; } |
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://blog.csdn.net/weixin_46571879/article/details/109538169