C语言贪食蛇实现

CSDN博客

贪食蛇小Demo

我们先来看一下C语言的贪食蛇代码,相对于面向对象的的语言,C语言是一门面向过程的语言,C语言写出来的代码都是顺着平常的思路来一步一步实现的,我们先来看C语言的代码

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
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<time.h>
//函数声明区
void Pos(int x, int y);//光标位置设定
void muban();//打印模板
void initSnake();//蛇身的初始化
void creatFood();//创建食物
char reDirection();//识别方向
int snakeMove();//蛇移动
int crossWall();//不能穿墙
int eatSelf();//不能吃自己

typedef struct Snake//相当于蛇一个节点
{
int x;//横坐标
int y;//纵坐标
struct Snake *next;
}snake;
snake *head;//头指针
snake *p;//用来遍历
snake *food1;//用来标记的
char status='L';//初始方向的状态,解决开始会动的问题
int score=0;//分数
int add=10;//一个食物的分
int leap=0;//用来标志是否结束,0没有,1代表蛇死了代表结束了
int endleap=0;//结束标志 1就是结束
int sleepTime=500;
void initSnake()//蛇身初始化,给定一个长度,用结构体表示是蛇的骨架,真正要显示出来是打印▇
{
int i;
snake *tail;//尾指针
tail=(snake*)malloc(sizeof(snake));//第一个节点/头结点
tail->x=30;//2的倍数,因为方块的长是两个单位
tail->y=10;//1个单位
tail->next=NULL;
for(i=1;i<=4;i++)//尾插法
{
head=(snake*)malloc(sizeof(snake));//申请一个节点
head->next=tail;//连接成链
head->x=30-2*i;//下一个节点的位置
head->y=10;
tail=head;
}
//遍历打印出来
while(tail!=NULL)
{
Pos(tail->x,tail->y);
printf("▇");
tail=tail->next;
}


}

char reDirection()//识别用户按下的键值 保留方向值
{
if(GetAsyncKeyState(VK_F7))//热键
{
if(sleepTime>300)//最多减到300
{
sleepTime-=50;//每次减50
add++;//每次食物加1分
}
}
if(GetAsyncKeyState(VK_F8))
{
if(sleepTime<800)//最多加到800
{
sleepTime+=50;//每次加50
add--;//每次食物减1分
}
}
if(GetAsyncKeyState(VK_UP)&&status!='D')
status='U';
if(GetAsyncKeyState(VK_DOWN)&&status!='U')
status='D';
if(GetAsyncKeyState(VK_LEFT)&&status!='R')
status='L';
if(GetAsyncKeyState(VK_RIGHT)&&status!='L')
status='R';
return status;
}
void Pos(int x, int y)//设置光标位置,从哪里开始输出
{
COORD pos;//表示一个字符在控制台屏幕上的坐标,左上角(0,0)
HANDLE hOutput;
pos.X = x;
pos.Y = y;
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);//返回标准的输入、输出或错误的设备的句柄,也就是获得输入、输出/错误的屏幕缓冲区的句柄
SetConsoleCursorPosition(hOutput, pos);
}


void creatFood()//创建食物
{
snake *food;//创造一个食物
food=(snake*)malloc(sizeof(snake));
srand((unsigned int)time(NULL));//随着时间变化,产生不一样种子,就会得到没规律的食物
while(food->x%2!=0)
{
food->x=rand()%56+2;
}
food->y=rand()%23+1;

//上面虽然解决了食物不会出现在城墙里,没有考虑食物出现在蛇本身里面
p=head;//用p来遍历
while(p!=NULL)//解决食物出现在蛇本身
{
if(food->x==p->x&&food->y==p->y)
{
free(food);
creatFood();
}
p=p->next;
}
Pos(food->x,food->y);
food1=food;//food1用来标记的作用
printf("▇");
Pos(70,20);//解决有光标闪烁的办法
printf("您的分数是:%d",score);
}
void muban()
{
int i;
for(i=0;i<=60;i+=2)//方块水平方向占两个单位
{
Pos(i,0);
printf("▇");//上行
Pos(i,26);
printf("▇");//下行
}
for(i=0;i<=25;i+=1)//方块垂直方向占1个单位
{
Pos(0,i);//左列
printf("▇");
Pos(60,i);//右列
printf("▇");
}
}

int snakeMove()
{
snake *nexthead;
nexthead=(snake*)malloc(sizeof(snake));
if(status=='R')//向右走
{
nexthead->x=head->x+2;
nexthead->y=head->y;
if(nexthead->x==food1->x&&nexthead->y==food1->y)//吃掉了食物
{
nexthead->next=head;
head=nexthead;
p=head;//p用来从头遍历,打印方块
while(p!=NULL)
{
Pos(p->x,p->y);
printf("▇");
p=p->next;
}//吃掉了食物得创造
score=score+add;
creatFood();

}
else//没有食物
{
nexthead->next=head;
head=nexthead;
p=head;//p用来从头遍历,打印方块
while(p->next->next!=NULL)
{
Pos(p->x,p->y);
printf("▇");
p=p->next;
}
Pos(p->next->x,p->next->y);
printf(" ");//会带来一个光标闪烁
Pos(70,20);//解决办法
printf("您的分数是:%d",score);
free(p->next);
p->next=NULL;
}
}
if(status=='L')//向左走
{
nexthead->x=head->x-2;
nexthead->y=head->y;
if(nexthead->x==food1->x&&nexthead->y==food1->y)//吃掉了食物
{
nexthead->next=head;
head=nexthead;
p=head;//p用来从头遍历,打印方块
while(p!=NULL)
{
Pos(p->x,p->y);
printf("▇");
p=p->next;
}//吃掉了食物得创造
score=score+add;
creatFood();

}
else//没有食物
{
nexthead->next=head;
head=nexthead;
p=head;//p用来从头遍历,打印方块
while(p->next->next!=NULL)
{
Pos(p->x,p->y);
printf("▇");
p=p->next;
}
Pos(p->next->x,p->next->y);
printf(" ");
Pos(70,20);//解决办法
printf("您的分数是:%d",score);
free(p->next);
p->next=NULL;
}
}
if(status=='U')//向上走
{
nexthead->x=head->x;
nexthead->y=head->y-1;
if(nexthead->x==food1->x&&nexthead->y==food1->y)//吃掉了食物
{
nexthead->next=head;
head=nexthead;
p=head;//p用来从头遍历,打印方块
while(p!=NULL)
{
Pos(p->x,p->y);
printf("▇");
p=p->next;
}//吃掉了食物得创造
score=score+add;
creatFood();

}
else//没有食物
{
nexthead->next=head;
head=nexthead;
p=head;//p用来从头遍历,打印方块
while(p->next->next!=NULL)
{
Pos(p->x,p->y);
printf("▇");
p=p->next;
}
Pos(p->next->x,p->next->y);
printf(" ");
Pos(70,20);//解决办法
printf("您的分数是:%d",score);
free(p->next);
p->next=NULL;
}
}
if(status=='D')//向下走
{
nexthead->x=head->x;
nexthead->y=head->y+1;
if(nexthead->x==food1->x&&nexthead->y==food1->y)//吃掉了食物
{
nexthead->next=head;
head=nexthead;
p=head;//p用来从头遍历,打印方块
while(p!=NULL)
{
Pos(p->x,p->y);
printf("▇");
p=p->next;
}//吃掉了食物得创造
score=score+add;
creatFood();

}
else//没有食物
{
nexthead->next=head;
head=nexthead;
p=head;//p用来从头遍历,打印方块
while(p->next->next!=NULL)
{
Pos(p->x,p->y);
printf("▇");
p=p->next;
}
Pos(p->next->x,p->next->y);
printf(" ");
Pos(70,20);//解决办法
printf("您的分数是:%d",score);
free(p->next);
p->next=NULL;
}
}

Sleep(sleepTime);//蛇移动的速度,里面是毫秒,越大速度越慢
status=reDirection();//判别下方向先
if(crossWall()==1||eatSelf()==1)
//exit(0);//直接把程序关闭了
endleap=1;
return endleap;

}

int crossWall()//判断蛇有没穿透墙
{
if(head->x==0||head->y==0||head->x==60||head->y==25)
leap=1;
return leap;
}
int eatSelf()//判断是否咬到了自己
{
snake *q;//遍历的
q=head->next;
while(q!=NULL)
{
if(q->x==head->x&&head->y==q->y)
leap=1;
q=q->next;
}
return leap;
}
//打印食物的时候会出现光标,解决办法就是引开它

int main()
{
muban();//打印模板
initSnake();//初始化蛇
creatFood();//创建食物
while(1)//死循环,让蛇一直动起来,直到蛇死了
{
if(snakeMove()==1)//判断是否结束
{
Pos(70,23);
printf("蛇死了");
system("pause");//用来暂停
Pos(70,24);//解决press any key to continue 在该地点打印 大家试下
break;
}

}
printf("是否继续游戏,y or n:");//y 继续
if(getch()=='y')//重新游戏
{
//蛇一开始就死了,因为全局变量没有恢复原值,仍然保留上一局的值
status='L';//初始方向的状态,解决开始会动的问题
score=0;//分数
add=10;//一个食物的分
leap=0;//用来标志是否结束,0没有,1代表蛇死了代表结束了
endleap=0;//结束标志 1就是结束
sleepTime=500;
system("cls");//清理屏幕
main();//自己调用自己 看不一样的编译器,vc6.0允许调用自己
}
if(getch()=='n')
{
Pos(70,25);//定一个位置,再打印press
exit(0);//退出程序
}

return 0;
}

//蛇的速度变化,每个食物的分数增加
//是否继续游戏
//按键的作用

在C语言中,我们利用定义一个一个函数模块来实现蛇的基础实现,然后定义蛇的一个结构体,利用链表的知识来串联蛇身体,来让蛇身连接起来并走动起来。

/*go语言实现的贪食蛇请见博下一章/

-------------本文结束感谢您的阅读-------------

本文标题:C语言贪食蛇实现

文章作者:Wuman

发布时间:2018年09月05日 - 12:09

最后更新:2018年09月05日 - 13:09

原始链接:http://yoursite.com/2018/09/05/C语言贪食蛇实现/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。