C语言实现简单贪吃蛇小游戏

时间:2022-12-03 07:30:52

本文实例为大家分享了C语言实现简单贪吃蛇的具体代码,供大家参考,具体内容如下

依然是非常传统的贪吃蛇小游戏,网上很多教程,配置好ege图形库就好,不然没有grapics.h另外,还需要添加snakes.h,直接上代码吧,注释很详细了。觉得难度有一部分来源于配置图形库。

snakes.h

?
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
void welcome();
void initSnake();
void createPoint();
void drawSnake();
void drawRandomPoint();
void view();
void sMove();
void changeHead();
void keyControl(int key);
void drawScore(int x, int y, int score_size);
int isGetPoint();
void againGame();
int isGameOver();
#define WINWIDTH 800 //窗口的宽度
#define WINHIGH 544 //窗口的高度
 
#define S_POOLX 30 //游戏池开始的横坐标
#define S_POOLY 30 //游戏池开始的纵坐标
 
#define POINT_W  10 //构成蛇的小方块的宽度
 
#define E_POOLX (S_POOLX+(POINT_W+2)*43-2)  //游戏池结束的横坐标
#define E_POOLY (S_POOLY+(POINT_W+2)*33-2)  //游戏池结束的纵坐标
 
#define MAX_SNAKE 100  //蛇最大的长度
 
// 定义一个枚举类型,表示蛇运动的方向
enum dire
{
 LEFT=1,
 RIGHT,
 UP,
 DOWN,
};
 
struct point
{
 int x;    //点的横坐标
 int y;    //点的纵坐标
 color_t coler;  //点的颜色
}snake[MAX_SNAKE];  //定义一个点的结构体,包括横纵坐标,以及点的颜色。并定义一个名为snake的点的数组作为蛇的数据存放

main.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
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
#include <graphics.h>
#include "snake.h"
#include <stdio.h>
 
int s_length = 0; //存放蛇的长度
int score =0;  //存放获得的分数
enum dire s_direction = RIGHT; //初始化蛇的方向是向右运动
 
struct point r_point;   //定义一个point结构体来存放随机出现点的数据,即蛇的食物
 
 
/**********************************************
 * 游戏结束时显示函数
 * 名称:void AgainGame()
 * 功能:绘制游戏开始界面
 *********************************************/
void againGame()
{
 //声明一个img图片对象
 PIMAGE img;
 
 cleardevice();    //清屏
 
 //用newimage在initgraph后创建这个对象。但记得要在不使用的时候delimage
 img = newimage();
 getimage(img, "C://Users//Administrator//Desktop//图片//snake.end!.jpg");  //加载游戏结束的图片
 putimage(0, 0, img);       //显示游戏结束的图片
 
 drawScore(360, 250, 60);  //绘制显示得分
 
 while(getch() != 'r'//等待用户按键,若等于'r'键,则跳出结束界面,即重新开始程序
 {
  if(!is_run())
  {
   break//防止无法关闭窗口
  }
 }
 delimage(img);  //销毁img变量
}
 
/************************************************
 *判断游戏是否结束函数
 *名称:int isGameOver()
 *功能:通过检查蛇是否出界或者碰到自身身体来判断是否游戏结束
 *返回值:为1则表示游戏结束,为0则游戏进行中。
 ***********************************************/
int isGameOver()
{
 int i;
 
 //判断蛇头是否超出边界
 if((snake[s_length-1].x < S_POOLX) || (snake[s_length-1].x > E_POOLX-POINT_W) ||(snake[s_length-1].y < S_POOLY) ||(snake[s_length-1].y > E_POOLY-POINT_W))
 {
  return 1;
 }
 else
 {
  for(i=0; i< s_length-1; i++) //通过for循环来判断蛇头是否与蛇神碰撞
  {
   if((snake[i].x==snake[s_length-1].x) && (snake[i].y==snake[s_length-1].y))
   {
    return 1;
   }
  }
  return 0;
 }
}
 
/************************************************
 *判断蛇是否迟到食物函数
 *名称:int isGetPoint()
 *功能:通过检查蛇头是否和食物重合来判断是否吃到食物
 *返回值:为1则表示吃到食物,为0则表示还未吃到。
 ***********************************************/
int isGetPoint()
{
 if((snake[s_length-1].x==r_point.x) && (snake[s_length-1].y == r_point.y)) //判断舌头是否和食物坐标重合
 {
  s_length++;    //更新蛇的长度
 
  snake[s_length-1].x=r_point.x;
  snake[s_length-1].y=r_point.y;    //将食物的坐标添加到蛇snake的数组中,并将食物坐标填充进去
  snake[s_length-1].coler = r_point.coler;
 
  score += 10;   //得分加10
  changeHead();   //改变蛇头的坐标为运动方向的下一个点的坐标
 
  return 1;    //若吃到食物则返回1
 }
 
 return 0;     //若没吃到食物则返回0
}
 
 
/**********************************************
 * 得分的显示函数
 * 名称:void drawScore(int x, int y, int score_size)
 * 功能:按照参数中的坐标和大小显示 蛇的得分
 *********************************************/
void drawScore(int x, int y, int score_size)
{
 char s[10];
 setcolor(EGERGB(0x00, 0x0, 0x0));  //设置字体颜色
 setfont(score_size, 0, "幼圆");   //设置字体
 setbkmode(TRANSPARENT);     //设置字体背景为透明
 
 sprintf(s,"%d",score);     //将整型的score 转换成字符串
 outtextxy(x, y, s);      //显示字体
}
 
/************************************************
 *按键控制函数
 *名称:void keyControl(int key)
 *参数:int key ,表示按键的键值。
 *功能:处理蛇的左转、右转、上转和下转,以及游戏的暂停/启动
 ***********************************************/
void keyControl(int key)
{
 switch(key)
 {
  case VK_SPACE:  //暂停设置
   getch();
   getch();
   break;
  case 38:   //按方向上键,改变蛇向上运动
   if(s_direction != DOWN)
   {
    s_direction = UP;
   }
 
   break;
 
  case 40:   //按方向下键, 改变蛇向下运动
   if(s_direction != UP)
   {
    s_direction = DOWN;
   }
   break;
 
  case 37:   //按下方向左键,改变蛇向左运动
   if(s_direction != RIGHT)
   {
    s_direction = LEFT;
   }
   break;
 
  case 39:   //按下方向右键,改变蛇向右运动
   if(s_direction != LEFT)
   {
    s_direction = RIGHT;
   }
   break;
 }
}
 
/************************************************
 *更新蛇的运动函数
 *名称:void sMove()
 *功能:根据运动方向,更新蛇的坐标
 ***********************************************/
void sMove()
{
 int n;
 
 //依次改变蛇身体的坐标,规则为,前一个点的坐标传递给下一个点。
 for(n=1; n<s_length; n++)
 {
  snake[n-1].x = snake[n].x;
  snake[n-1].y = snake[n].y;
 }
 changeHead();  //根据蛇的运动方向,改变蛇头的坐标
}
 
/************************************************
 *改变蛇头的坐标函数
 *名称:void changeHead()
 *功能:根据运动方向,更新蛇头的坐标
 ***********************************************/
void changeHead()
{
 switch(s_direction)   //根据方向,改变相应的坐标更新
 {
  case RIGHT:
   snake[s_length-1].x += (POINT_W+2);
   break;
 
  case LEFT:
   snake[s_length-1].x -= (POINT_W+2);
   break;
 
  case UP:
   snake[s_length-1].y -= (POINT_W+2);
   break;
 
  case DOWN:
   snake[s_length-1].y += (POINT_W+2);
   break;
 
  default :
   break;
 
 }
}
 
/**************************
//初始化函数
//名称:void initSanke()
//功能:初始化蛇身体、运动方向、蛇的长度变量、得分变量
// ************************/
 
/**************************
//初始化函数
//名称:void initSanke()
//功能:初始化蛇身体、运动方向、蛇的长度变量、得分变量
// ************************/
void initSnake()
{
 snake[0].coler = 0x00ff00;
 snake[0].x = 10*(POINT_W+2) + S_POOLX;
 snake[0].y = 13*(POINT_W+2) + S_POOLY;
 
 snake[1].coler = 0x00ff00;
 snake[1].x = snake[0].x + POINT_W+2;
 snake[1].y = snake[0].y ;
 
 snake[2].coler = 0x00ff00;
 snake[2].x = snake[1].x + POINT_W+2;
 snake[2].y = snake[1].y;    //设置蛇的初始长度为3个方格
 
 s_length =3;    //初始化蛇的长度为3
 s_direction = RIGHT;  //初始化蛇运动方向为向右
 score =0;     //初始化得分为0
}
 
 
/************************************************
 *蛇的食物生成函数
 *名称:void createPoint()
 *功能:通过随机数产生食物所在点的坐标,并设置食物的颜色
 ***********************************************/
void createPoint()
{
 //随机生成食物所在点的坐标。POINT_W 表示食物的宽度,+2的目的是让方块之间留有空隙
 r_point.x = random(29)*(POINT_W+2) + S_POOLX;
 r_point.y = random(26)*(POINT_W+2) + S_POOLY;
 
 //设置食物的颜色
 r_point.coler = 0x00ff00;
}
 
/**********************************************
 *贪吃蛇体的显示函数
 * 名称:void drawSnake()
 * 功能:画出蛇体的形状和颜色
 * 即将结构体数组snake中的已有数据,全部展现在屏幕上。
 *********************************************/
void drawSnake()
{
 int n;
 
 for(n=0; n<s_length; n++)
 {
  if(n==s_length-1)   //若是蛇头,则绘制形状为空心圆,颜色为白色
  {
   setfillcolor(0xffffff);
   fillellipse(snake[n].x +POINT_W/2, snake[n].y+POINT_W/2,POINT_W,POINT_W);
  }
  else      //若是蛇身体,则绘制形状为实心正方形,宽度为POINT_W,
  {
   setfillcolor(snake[n].coler);
   bar(snake[n].x, snake[n].y, snake[n].x + POINT_W, snake[n].y + POINT_W);
  }
 }
}
 
 
/**********************************************
 *随机产生的蛇食物的显示函数
 * 名称:void drawRandomPoint()
 * 功能:画出蛇食物的形状和颜色
 * 即将结构体r_point中的已有数据,展现在屏幕上。
 *********************************************/
void drawRandomPoint()
{
 setfillcolor(r_point.coler);  //设置填充颜色
 bar(r_point.x, r_point.y, r_point.x+POINT_W, r_point.y+POINT_W); //绘制实心矩形
}
 
/**********************************************
 * 游戏进行时的显示函数
 * 名称:void view()
 * 功能:根据蛇的数据,不断更新绘制,蛇、食物、得分、背景显示
 *********************************************/
void view()
{
 // 清屏
 cleardevice();
 
  //加载背景图片
 PIMAGE img;
 img = newimage();
 getimage(img, "C://Users//Administrator//Desktop//图片//snake.mid!.jpg");
 putimage(0,0,img);
 
 setcolor(0x00ff00);
 rectangle(S_POOLX,S_POOLY,E_POOLX,E_POOLY);
 
 drawSnake();
 drawRandomPoint();
 drawScore(600, 100, 80);
 delimage(img);
}
 
/**********************************************
 * 游戏开始前的界面显示函数
 * 名称:void welcome()
 * 功能:绘制游戏开始界面
 *********************************************/
void welcome()
{
 //加载背景图片
 PIMAGE img;
 img = newimage();
 getimage(img, "C://Users//Administrator//Desktop//图片//snake.end!.jpg");
 putimage(0,0,img);
 
 //打印文字
 char s[] = "press any key to start!";
 setcolor(0x000000);
 setfont(20, 0, "幼圆");
 setbkmode(TRANSPARENT);
 outtextxy(250, 350, s);
 
 getch();
 delimage(img);
 
}
 
/****************************************************
//主循环函数
//名称:void mainloop()
//功能:本函数是程序的核心框架和核心流程
// **************************************************/
void mainloop()
{
 double timeNow = 0, timeBefor = 0; //定义两个double变量来计算程序运行时间s
 key_msg k = {0};
 
 welcome();  //程序欢迎界面
 
 while(is_run()) //is_run() 判断窗口是否关闭
 {
  initSnake(); //初始化
  createPoint(); //创建蛇的食物,即一个点
 
  for ( ; is_run(); delay_fps(60) )
  {
   if(isGameOver())
   {
    break; //判断是否超过边界或碰到自身
   }
 
   //处理按键操作
   while(kbmsg())
   {
    k = getkey();
    if(k.msg == key_msg_down)
    {
     keyControl(k.key); //根据按键值,来变换蛇的运动方向
    }
 
   }
 
   timeNow = fclock();     //获取当前时间
   if((timeNow - timeBefor) >= 0.2 ) //用当前的时间减去上一次记录的时间如果超过0.2秒则,移动一格。
   {
    sMove();
    timeBefor = timeNow;
   }
 
   if(isGetPoint())    //判断蛇是否迟到食物
   {
    createPoint();    //创建一个新的食物
   }
 
   view();        //显示
  }
 
  againGame();  //是否再来一局
 }
}
 
 
int main(void)
{
 //1、点击右上角X的时候,程序不主动结束,只是将窗口关闭
 //2、绘图更新模式改为手动跟新,仅当调用delay_ms、delay_fps 等这种函数时候,才去更新画面,避免闪烁
 //3、ege 图形库的默认设置
 
 setinitmode(INIT_ANIMATION);
 // 图形初始化,窗口尺寸800x544
 initgraph(WINWIDTH, WINHIGH);
 
 //设置窗口的标题
 setcaption("贪吃蛇游戏");
 
 // 随机数初始化,如果需要使用随机数的话
 randomize();
 
 // 程序主循环
 mainloop();
 
 // 关闭绘图设备
 closegraph();
 
 return 0;
}

素材截图

(1)welcome.png

C语言实现简单贪吃蛇小游戏

(2)game.png

C语言实现简单贪吃蛇小游戏

(3)gameover.png

C语言实现简单贪吃蛇小游戏

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/weixin_45619006/article/details/108463557