C语言贪吃蛇经典小游戏

时间:2022-02-28 08:21:35

一、贪吃蛇小游戏简介:

        用上下左右控制蛇的方向,寻找吃的东西,每吃一口就能得到一定的积分,而且蛇的身子会越吃越长,身子越长玩的难度就越大,不能碰墙,也不能咬到自己的身体,等到了一定的分数,就能过关。 

二、函数框架

C语言贪吃蛇经典小游戏

三、数据结构

?
1
2
3
4
5
6
typedef struct Snake
{
  size_t x; //行
  size_t y; //列
  struct Snake* next;
}Snake, *pSnake;

定义蛇的结构体,利用单链表来表示蛇,每个结点为蛇身体的一部分。 

四、代码实现(vs2010  c语言)

1.Snake.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
42
#ifndef __SNAKE_H__
#define __SNAKE_H__
 
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <time.h>
#include <malloc.h>
#include <assert.h>
//标识地图大小
#define ROW_MAP 10  //地图的行
#define COL_MAP 20  //地图的列
#define SUCCESS_SCORE 10//通关分数
enum Direction //蛇行走的方向
{
  R, //右
  L, //左
  U, //上
  D //下
}Direction;
 
enum State
{
  ERROR_SELF, //咬到自己
  ERROR_WALL, //撞到墙
  NORMAL,   //正常状态
  SUCCESS   //通关
}State;
 
typedef struct Snake
{
  size_t x; //行
  size_t y; //列
  struct Snake* next;
}Snake, *pSnake;
 
 
void StartGame();
void RunGame();
void EndGame();
 
#endif

2.Snake.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 "Snake.h"
 
 
pSnake head = NULL; //定义蛇头指针
pSnake Food = NULL; //定义食物指针
 
int sleeptime = 500;//间隔时间,用来控制速度
int Score = 0; //总分
int everyScore = 1; //每步得分
 
//定义游戏中用到的符号
const char food = '#';
const char snake = '*';
 
void Pos(int x, int y)  //控制输出光标
{
  COORD pos; //pos为结构体
  pos.X = x; //控制列
  pos.Y = y; //控制行
  SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);//读取标准输出句柄来控制光标为pos
}
 
void Face()
{
  system("color 0C");
  printf("*******************************************************\n");
  printf("*        Welcome to Snake Game!        *\n");
  printf("*                           *\n");
  printf("*       ->开始游戏请按 enter键         *\n");
  printf("*       ->退出游戏请按 esc键          *\n");
  printf("*       ->暂停游戏请按 space键         *\n");
  printf("*       ->通过上下左右键来控制蛇的移动     *\n");
  printf("*       ->通过F1键减速    F2键加速     *\n");
  printf("*******************************************************\n");
}
void Map()  //初始化地图
{
  int i = 0;
  for(i = 0; i<COL_MAP; i+=2)  //打印上下边框(每个■占用两列)
  {
    Pos(i, 0);
    printf("■");
    Pos(i, ROW_MAP-1);
    printf("■");
  }
  for(i = 0; i<ROW_MAP; i++)  //打印左右边框
  {
    Pos(0, i);
    printf("■");
    Pos(COL_MAP-2, i);
    printf("■");
  }
}
void PrintSnake() //打印蛇
{
  pSnake cur = head;
  while(cur)
  {
    Pos(cur->y, cur->x);
    printf("%c", snake);
    cur = cur->next;
  }
}
void InitSnake()  //初始化蛇身
{
  int initNum = 3;
  int i = 0;
  pSnake cur;
  head = (pSnake)malloc(sizeof(Snake));
  head->x = 5;
  head->y = 10;
  head->next = NULL;
 
  cur = head;
  for(i = 1; i < initNum; i++)
  {
    pSnake newNode = (pSnake)malloc(sizeof(Snake));
    newNode->x = 5+i;
    newNode->y = 10;
    newNode->next = NULL;
    cur->next = newNode;
    cur = cur->next;
  }
 
  PrintSnake();
}
 
void CreateFood() //在地图上随机产生一个食物
{
  pSnake cur = head;
  Food = (pSnake)malloc(sizeof(Snake));
 
  //产生x~y的随机数 k=rand()%(Y-X+1)+X;
  srand((unsigned)time(NULL));
  Food->x = rand()%(ROW_MAP-2 - 1 + 1)+1;
  Food->y = rand()%(COL_MAP-3 - 2 + 1)+2;
  Food->next = NULL;
  while(cur)  //检查食物是否与蛇身重合
  {
    if(cur->x == Food->x && cur->y == Food->y)
    {
      free(Food);
      Food = NULL;
      CreateFood();
      return;
    }
    cur = cur->next;
  }
  Pos(Food->y, Food->x);
  printf("%c", food);
}
 
void StartGame() //游戏开始的所有设置
{
  Face();
  system("pause");
 
  if(GetAsyncKeyState(VK_RETURN))
  {
    system("cls");
    Pos(COL_MAP+5, 1);
    printf("当前分数/通关分数:");
    Pos(COL_MAP+20, 1);
    printf("%d/%d", Score, SUCCESS_SCORE);
    Pos(COL_MAP+5, 2);
    printf("当前分每步得分:");
    Pos(COL_MAP+20, 2);
    printf("%d", everyScore);
    Pos(COL_MAP+5, 3);
    printf("\n");
    Pos(COL_MAP+5, 4);
    printf("速度越快 得分越高哦!!\n");
 
    Map();
    InitSnake();
    CreateFood();
  }
  else if(GetAsyncKeyState(VK_ESCAPE))
  {
    exit(0);
  }
}
 
int IsCrossWall()       //判断是否碰到墙
{
  if(head->x <= 0 || head->x >= ROW_MAP-1
    ||head->y <= 1 || head->y >= COL_MAP-2)
  {
    State = ERROR_WALL;
    return 0;
  }
  return 1;
}
 
int IsEatSelf(pSnake newHead) //判断是否咬到自己
{
  pSnake cur = head;
  assert(newHead);
  while(cur)
  {
    if(cur->x == newHead->x && cur->y == newHead->y)
    {
      State = ERROR_SELF;
      return 0;
    }
    cur = cur->next;
  }
  return 1;
}
 
int IsFood(pSnake pos) //判断该位置是不是食物
{
  assert(pos);
  if(pos->x == Food->x && pos->y == Food->y)
  {
    return 1;
  }
  return 0;
}
 
void SnakeMove()  //蛇移动一次
{
  pSnake newHead = NULL;
  newHead = (pSnake)malloc(sizeof(Snake));
 
  if(Direction == R)
  {
    newHead->x = head->x;
    newHead->y = head->y+1;
    newHead->next = head;
  }
  else if(Direction == L)
  {
    newHead->x = head->x;
    newHead->y = head->y-1;
    newHead->next = head;
  }
  else if(Direction == U)
  {
    newHead->x = head->x-1;
    newHead->y = head->y;
    newHead->next = head;
   
  }
  else if(Direction == D)
  {
    newHead->x = head->x+1;
    newHead->y = head->y;
    newHead->next = head;
  }
 
  if(IsFood(newHead))
  {
    head = newHead;
    PrintSnake();
    CreateFood();
    Score += everyScore;
    Pos(COL_MAP+20, 1);
    printf("%d/%d", Score, SUCCESS_SCORE);
    if(Score >= SUCCESS_SCORE)
    {
      State = SUCCESS;
    }
  }
  else
    {
      if(IsCrossWall() && IsEatSelf(newHead))
      {
        pSnake cur = NULL;
        head = newHead;
        cur = head;
        //删除蛇尾并打印
        while(cur->next->next != NULL)
        {
          Pos(cur->y, cur->x);
          printf("%c", snake);
          cur = cur->next;
        }
         
        Pos(cur->y, cur->x);
        printf("%c", snake);
        Pos(cur->next->y, cur->next->x);
        printf(" "); //打印空格来覆盖频幕上的蛇尾
        free(cur->next);
        cur->next = NULL;
      }
      else
      {
        free(newHead);
        newHead = NULL;
      }
  }
}
 
void Pause()
{
  while(1)
  {
    Sleep(sleeptime);
    if(GetAsyncKeyState(VK_SPACE))
    {
      break;
    }
  }
}
 
void ControlSnake() //用键盘控制游戏
{
  if(GetAsyncKeyState(VK_UP) && Direction!=D)
  {
    Direction = U;
  }
  else if(GetAsyncKeyState(VK_DOWN) && Direction!=U)
  {
    Direction = D;
  }
  else if(GetAsyncKeyState(VK_LEFT) && Direction!=R)
  {
    Direction = L;
  }
  else if(GetAsyncKeyState(VK_RIGHT) && Direction!=L)
  {
    Direction = R;
  }
  else if(GetAsyncKeyState(VK_F1))
  {
    if(sleeptime != 500)
    {
      sleeptime = 500;
      everyScore = 1;
      Pos(COL_MAP+20, 2);
      printf("%d", everyScore);
    }
  }
  else if(GetAsyncKeyState(VK_F2))
  {
    if(sleeptime != 300)
    {
      sleeptime = 300;
      everyScore = 2;
      Pos(COL_MAP+20, 2);
      printf("%d", everyScore);
    }
  }
  else if(GetAsyncKeyState(VK_SPACE))
  {
    Pause();
  }
  else if(GetAsyncKeyState(VK_ESCAPE))
  {
    exit(0);
  }
}
 
void StateGame() //判断游戏失败或成功
{
  if(State == ERROR_SELF)
  {
    system("cls");
    printf("很遗憾,蛇咬到自己,游戏失败!\n");
  }
  else if(State == ERROR_WALL)
  {
    system("cls");
    printf("很遗憾,蛇碰到墙壁,游戏失败!\n");
  }
  else if(State == SUCCESS)
  {
    system("cls");
    printf("恭喜您,已通关!!!\n");
  }
   
}
void RunGame()
{
  Direction = R; //蛇初始行走方向为右
  State = NORMAL;//游戏初始为正常状态
  while(1)
  {
    ControlSnake();
    SnakeMove();
    if(State != NORMAL)
    {
      StateGame();
      break;
    }
    Sleep(sleeptime);
  }
}
 
void EndGame() //释放链表并恢复默认值
{
  pSnake cur = head;
  while(cur)
  {
    pSnake del = cur;
    cur = cur->next;
    free(del);
    del = NULL;
  }
  head = NULL;
  if(Food != NULL)
  {
    free(Food);
    Food = NULL;
  }
  Score = 0;
  everyScore = 1;
  sleeptime = 500;
}

3.Test.c

?
1
2
3
4
5
6
7
8
9
10
11
12
13
#include "Snake.h"
 
int main()
{
  while(1)
  {
    StartGame();
    RunGame();
    EndGame();
  }
  system("pause");
  return 0;
}

五、运行界面展示

1.欢迎界面

 C语言贪吃蛇经典小游戏

2.游戏界面

C语言贪吃蛇经典小游戏

小小的c语言项目,用来练手,仅供参考哦!!
谢谢阅读,如有问题,欢迎提出。

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

原文链接:http://blog.csdn.net/XHfight/article/details/51676109