Win下控制台简单贪吃蛇实现

贪吃蛇

???算是对大一课设的交代>>>,代码抄过来的

vs2020下编译,仅使用Sleep()和system(“cls”),_kbhit(),等几个win api

结构: —— main.c global.c global.h

主要思路:2维数组每个点分别存墙(1),空地(0),蛇身体(2),食物点(3).然后遍历2维数组printf绘图

蛇身体长度通过int* body[]指针数组指向对应地图点,


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
//#define _WINSOCK_DEPRECATED_NO_WARNINGS 

#include "global.h"

extern int overFlag;

int main(int argc,char *argv[])
{
while (1)
{
printf("输入y修改设置(否则按下任意键: ");
fflush(stdout);
if (_getch() == 'y')
{
GetSet();
}
//StartView(); /*游戏开始前的动画*/
StartGame();
printf("Game Over!!!\n 按下任意键结束 \n");
_getch();
overFlag = 1;
system("cls");
}
return 0;
}

global.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
#include "global.h"
/*
全局变量
*/

int speed = 30; /*蛇的移动速度*/
int mapArr[MAXX][MAXY]; /*坐标处的内容*/
int inputX = 50, inputY = 20; /*默认游戏的界面宽度和高度*/
int randX = -1, randY = -1; /*随机生成食物坐标值*/
int foodFlag = 0; /*判断是否更新食物*/
int sx = 1, sy = 1; /*设置蛇身坐标值*/
int l = 0; /*蛇身长度*/
int* body[MAXX * MAXY]; /*存储蛇身体的数组*/
char input; /*默认移动方向*/
int overFlag = 1; /*游戏介绍标志:撞墙or吃到自己*/
int moveX = 1,moveY = 1; /*游戏开始的动画坐标值*/
int moveFlag = 0; /*动画的循环判断*/

/*地图初始化*/
void InitMap()
{
for (int y = 0; y < inputY; y++)
{
for (int x = 0; x < inputX; x++)
{
/*边界赋值为1*/
if ((x == 0) || (x == inputX - 1) || (y == 0) || (y == inputY - 1))
{
mapArr[x][y] = 1;
}
else
{
mapArr[x][y] = 0;
}
}
}
return;
}

/*游戏界面设置*/
void GetSet()
{
printf("\n请输入游戏空间的宽度:\n");
scanf_s("%d",&inputX);
printf("\n请输入游戏空间的高度:\n");
scanf_s("%d",&inputY);
printf("\n请输入游戏速度(1~n):\n");
scanf_s("%d",&speed);
}

/*游戏开始前的动画??*/
void StartView()
{
moveX = 1, moveY = 1, moveFlag = 0;
int startFlag = 1;
InitMap();
while (startFlag)
{
SetMoveNum(); /*数字动画*/
PrintMap(); /*打印出游戏地图*/
printf("按任意键开始游戏:\n");
Sleep(10);
system("cls");
JudgeEnd(); /*去掉动画,恢复到初始状态*/
if (_kbhit()) //检测是否有输入
{
int c = _getch();
if ((c != '2') &&
(c != 'w') &&
(c != '8') &&
(c != 's') &&
(c != '4') &&
(c != 'a') &&
(c != '6') &&
(c != 'd'))
startFlag = 0;
}
}
}

void JudgeEnd()
{
int tmp = 1;
for (int j = 0; j < inputY; j++)
{
for (int i = 0; i < inputX; i++)
{
if (mapArr[i][j] == 0)
goto out;
}
}
//恢复动画前的效果
moveX = 1, moveY = 1;
InitMap();
moveFlag = 0;
out:
return;
}

/*打印每个坐标处的值对应的图标*/
void PrintMap()
{
//遍历一次mapArr
for (int y = 0; y < inputY; y++)
{
for (int x = 0; x < inputX; x++)
{
fflush(stdout);
switch (mapArr[x][y])
{
/*空白处*/
case 0:
printf(" ");
break;
/*围墙*/
case 1:
printf("+");
break;
/*蛇身体*/
case 2:
printf("*");
break;
/*食物*/
case 3:
printf("@");
}
}
printf("\n");
}
}

/*数字动画,效果看下面注释*/
void SetMoveNum()
{
/*
x 移动到 1~(inputX-2),
y 移动到 1~(inputY-2)
*/
// x从左到右, 此时在最上边
if ((moveY == 1 + moveFlag) && (moveX < inputX - 2 - moveFlag))
{
mapArr[moveX][moveY] = 2;
moveX++;
}
// y从上到下 , 此时在最右边
else if ((moveX == inputX - 2 - moveFlag) && (moveY < inputY - 2 - moveFlag))
{
mapArr[moveX][moveY] = 2;
moveY++;
}
// x从右到左, 此时在最下面
else if ((moveY == inputY - 2 - moveFlag) && (moveX > 1 + moveFlag))
{
mapArr[moveX][moveY] = 2;
moveX--;
}
// y从下到上, 此时在最左边
else if ((moveX == 1 + moveFlag) && (moveY > 1 + moveFlag))
{
mapArr[moveX][moveY] = 2;
moveY--;
if (moveY == 2 + moveFlag)
{
moveFlag++;
}
}
}

//游戏开始
void StartGame()
{
sx = 1, sy = 1, l = 0;
/*默认的移动方向*/
input = 'd';
for (int j = 0; j < l; j++)
{
body[j] = &mapArr[sx - j][sy];
}
while (overFlag)
{
InitMap();
SetSnakeNum(); //设置蛇的位置
SetRandNum(); //设置食物出现的位置
EatFood();
PrintMap();
StartMsg();
Sleep(1000/speed); //没想到调整速度,==调整刷新延迟
system("cls");
}
}

void StartMsg()
{
printf
("'2(top)', '8(down)', '4(left)', 6(right)' 或 \n'w(top)', 'a(left)', 's(down)', 'd(right)'\n控制方向(control the direction)\n");
}

//处理蛇是否吃了食物
void EatFood()
{
if (*body[0] == 3)
{
l++;
foodFlag = 0; // foodFlag=0表示要再次生成食物,
}
}

//设置食物出现位置
void SetRandNum()
{
srand((unsigned int)time(0));
//需要生成食物,但是又不是空地
while ((mapArr[randX + 1][randY + 1] != 0) && (foodFlag == 0))
{
randX = rand() % (inputX - 2);
randY = rand() % (inputY - 2);
}
mapArr[randX + 1][randY + 1] = 3;
foodFlag = 1; //生成成功
}

void SetSnakeNum()
{
if (_kbhit()) //判断是否有输入
{
int a = _getch();
switch (input)
{
//上一个是向上,那么这里只能向左和右
case 'w':
if (a == 'a' || a == 'd')
{
input = a;
}
break;
//上一个方向是向下,那么这里只能向左和右
case 's':
if (a == 'a' || a == 'd')
{
input = a;
}
break;
//上一个方向向左,那么这里只能向上和下
case 'a':
if (a == 'w' || a == 's')
{
input = a;
}
break;
//上一个方向向右,那么这里只能向上和下
case 'd':
if (a == 'w' || a == 's')
{
input = a;
}
break;
}
}
//input是刚刚从上面(输入)拿到新的有效方向
switch (input)
{
/*UP 向上*/
case 'w':
sy--;
break;
/*Down 向下*/
case 's':
sy++;
break;
/*Left 向左*/
case 'a':
sx--;
break;
/*Right 向右*/
case 'd':
sx++;
break;
}

//为什么吃了食物,没有立即边长,因为我们增加了L,在这里进行对地图赋值=2,等价于增长,
for (int i = l; i!=0 ; i--)
{
body[i] = body[i-1];//丢弃最后一个指针,所有元素向后移动
*body[i] = 2;
}
//移动蛇的身体(上面去掉一个,然后新增一个开头处,
body[0] = &mapArr[sx][sy];
if ((*body[0] == 1) || (*body[0] == 2)) //判断是否撞墙>>
overFlag = 0;
*body[0] = 2;//第一次l = 0,但是这里给赋值了
}

global.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
#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <conio.h>
#include <time.h>


#define MAXX 10000
#define MAXY 10000

void InitMap();
void GetSet();
void StartView();
void SetMoveNum();
void PrintMap();
void JudgeEnd();
void StartGame();
void SetSnakeNum();
void SetRandNum();
void EatFood();
void StartMsg();


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!