相信大家都玩过贪吃蛇,作为中山大学软件工程专业优秀的学生(说的当然不是我)怎么能连贪吃蛇都不会做呢?(胡言乱语)下面是我的贪吃蛇逻辑,写的比较low,欢迎大佬提出改进意见。
地图、身体、头
首先我们需要一个地图和初始的蛇,可以用一个二维的数组表示。直接手动输入地图和初始的蛇:
上面的定义为几个要素的符号,主要是为了改变图形,比如要把蛇头改为@,只要把SNAKE_HEAD改一下就行了。
下面申请几个数组,分别记录蛇的X,Y坐标和食物的X,Y坐标:
snake-move
这样,我们就有了蛇,接下来考虑怎么让蛇动起来:
伪代码:
WHILE not 游戏结束 DO
ch=等待输入
CASE ch DO
‘A’:左前进一步,break
‘D’:右前进一步,break
‘W’:上前进一步,break
‘S’:下前进一步,break
END CASE
怎么让蛇前进呢?首先,我们控制蛇头的移动:
然后,蛇头后面的身体移动到了原来蛇头的位置,然后其他身体移动到上一段身体的位置。这时候我们需要在移动最开始记录一下蛇头的位置:
int presnakeX = snakeX[snakeLength - 1];
int presnakeY = snakeY[snakeLength - 1];//记录原来蛇头的位置
身体移动的实现:
然后我们把地图上这些坐标的元素设为相应的符号:
但是,这样打出来的地图还会有上一次的蛇,那我们在移动最开始把地图上所有东西全设为空即可:
游戏开始、结束
现在,我们的蛇会跑了,但是我们知道,蛇碰到了障碍物或自己会死,也就是游戏结束。我们可以设定一个变量gamerunning=1,如果撞到了障碍物,gamerunning=0,当gamerunning=1时才进行游戏。
if (map[snakeX[snakeLength - 1]][snakeY[snakeLength - 1]] == WALL_CELL || map[snakeX[snakeLength - 1]][snakeY[snakeLength - 1]] == SNAKE_BODY)//判断是否游戏结束
{
GameOver();
}
食物
现在我们需要给游戏添加食物,蛇吃到食物会加长身体。因为吃到食物的运动和一般的运动不同,所以需要一个变量记录是否吃了食物。如果islonger=1则进行吃食物的运动。
蛇吃了食物(即头的坐标等于食物的坐标)长度加一,只需要将蛇头后面加一节而其他位置不动即可。食物通过一个函数food()生成:
添加身体:
当然运动前要清空蛇,吃了食物后要把食物的位置设为空。
主函数
好了,现在大体的设定已经完成,接下来是主函数。
int main(void)
{
srand(time(NULL));
food();//先生成食物
output();//开始先打印一遍地图
char control = 0;
while (gamerunning==1) {
scanf_s(" %c", &control, 1);
snakeMove(control);
output();
}
printf("Game Over!!!");
return 0;
}
output()是打印地图的函数,每运动一次要重新打印一遍地图,但是如果用printf打印,会出现一个又一个静态的地图,这样影响体验感。我们可以用刷屏函数来解决:
void output()//打印地图
{
system("cls");//刷屏
for (int i = 0; i < 12; ++i) {
printf("%s\n", map[i]);
}
}
OK现在我们的贪吃蛇就做好了。不过这个蛇还有很多不足。首先,输入方向键后要加回车才能运动。然后,蛇碰到障碍后要在随便按一个键游戏才会结束。这些问题我会在以后的学习中逐个改正。