激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - C/C++ - C語言循環鏈表實現貪吃蛇游戲

C語言循環鏈表實現貪吃蛇游戲

2021-10-03 22:31yzw丶 C/C++

這篇文章主要為大家詳細介紹了C語言循環鏈表實現貪吃蛇,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了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()函數

蛇的變長,當蛇吃到食物的時候,此時我們將食物的坐標變成蛇頭,然后進行重新的打印蛇,即可以有蛇變成的效果產生,實質為對循環鏈表進行元素的插入。

C語言循環鏈表實現貪吃蛇游戲

即通過這樣將食物的坐標插進去循環鏈表,達到蛇變成的效果
代碼如下

?
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

延伸 · 閱讀

精彩推薦
  • C/C++C語言實現電腦關機程序

    C語言實現電腦關機程序

    這篇文章主要為大家詳細介紹了C語言實現電腦關機程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    xiaocaidayong8482021-08-20
  • C/C++c++ 單線程實現同時監聽多個端口

    c++ 單線程實現同時監聽多個端口

    這篇文章主要介紹了c++ 單線程實現同時監聽多個端口的方法,幫助大家更好的理解和學習使用c++,感興趣的朋友可以了解下...

    源之緣11542021-10-27
  • C/C++C/C++經典實例之模擬計算器示例代碼

    C/C++經典實例之模擬計算器示例代碼

    最近在看到的一個需求,本以為比較簡單,但花了不少時間,所以下面這篇文章主要給大家介紹了關于C/C++經典實例之模擬計算器的相關資料,文中通過示...

    jia150610152021-06-07
  • C/C++學習C++編程的必備軟件

    學習C++編程的必備軟件

    本文給大家分享的是作者在學習使用C++進行編程的時候所用到的一些常用的軟件,這里推薦給大家...

    謝恩銘10102021-05-08
  • C/C++C語言中炫酷的文件操作實例詳解

    C語言中炫酷的文件操作實例詳解

    內存中的數據都是暫時的,當程序結束時,它們都將丟失,為了永久性的保存大量的數據,C語言提供了對文件的操作,這篇文章主要給大家介紹了關于C語言中文件...

    針眼_6702022-01-24
  • C/C++詳解c語言中的 strcpy和strncpy字符串函數使用

    詳解c語言中的 strcpy和strncpy字符串函數使用

    strcpy 和strcnpy函數是字符串復制函數。接下來通過本文給大家介紹c語言中的strcpy和strncpy字符串函數使用,感興趣的朋友跟隨小編要求看看吧...

    spring-go5642021-07-02
  • C/C++深入理解goto語句的替代實現方式分析

    深入理解goto語句的替代實現方式分析

    本篇文章是對goto語句的替代實現方式進行了詳細的分析介紹,需要的朋友參考下...

    C語言教程網7342020-12-03
  • C/C++C++之重載 重定義與重寫用法詳解

    C++之重載 重定義與重寫用法詳解

    這篇文章主要介紹了C++之重載 重定義與重寫用法詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下...

    青山的青6062022-01-04
主站蜘蛛池模板: 久久精品国产久精国产 | av电影院在线观看 | 日本免费大片免费视频 | 久久久久国产一区二区三区不卡 | 欧美一级淫片a免费播放口 九九视频精品在线 | 免费观看高清视频网站 | 久久久久久久久久综合 | 国产日本在线 | 男女羞羞的视频 | 久久久久9999 | 视频久久免费 | 欧美日韩免费看 | 久久精品久久久久 | 久久久青青草 | 99精品国产在热久久婷婷 | 国产精品久久久久久久亚洲按摩 | 中文字幕在线一 | 成人免费一区二区三区视频网站 | www久久综合 | 精品中文字幕久久久久四十五十骆 | 亚洲精品成人18久久久久 | 久久久国产精品网站 | 黄色的视频免费看 | 一区二区免费看 | 精品一区二区久久久久久久网精 | av人人 | 成人国产在线看 | 午夜看毛片 | 污污的视频在线观看 | 99久久一区二区 | 国产精品久久久久久久成人午夜 | 国产成人高潮免费观看精品 | 国产午夜精品久久久久久久蜜臀 | 免费国产人成网站 | 色视频在线观看 | 懂色粉嫩av久婷啪 | 素人视频免费观看 | 久久久久久久国产视频 | 久久精品av| 国产成人高潮免费观看精品 | 国产午夜电影 |