零基础教做贪吃蛇——(4)剩余函数讲解

emmm,昨天没有更新,,这个嘛。还是因为STM32的原因,,,昨天弄它的串口通信弄了一下午加半个晚上,,再加上降温了。。手冷,,昨天就没写。。今天因为妹妹开网课了,,我又给她把家里以前的台式拼起来,,所以耽误的不少时间。。在这里插入图片描述
好了,话不多说,我们来开始今天的主题,这是最后一章了,我会把剩余的函数都讲了它。大家看完后可以自己尝试着也写一个,或者找啥子像素鸟啊,五子棋啊啥子试试,原理都是通的。这些项目除了可以激发兴趣外,还可以加深你对c语言的理解。

moveSnake函数

这个函数可以说是整个游戏的核心函数了,我们一定要弄明白蛇在整个游戏中的移动的逻辑。
首先,蛇在地图初始化的时候已经被我们打印出来了,但是在游戏中,即使我们不操作,蛇也是会自动移动的,这个移动的方向初始化时是向上,其他时候就是我们上次操作时的方向。
怎么样显示蛇“移动”的这个效果嘞?嘿嘿,通过坐标运算,把蛇的身子的其他值往前一个移动就可以了。

	for (k = snake.len - 1; k>0; k--)//蛇的身子一格一格的移动
	{
		snake.x[k] = snake.x[k - 1];
		snake.y[k] = snake.y[k - 1];
	}

并且蛇在移动时,如果没有吃到过果子,是没有长大的。所以我们渲染蛇向前移动时,最后一格的蛇尾“#”也要变成“ ”
同时,使用键盘控制蛇的移动时,如果蛇是向上走的,则你输入“S”向下是无效的。即需要考虑操作的合理性。
这个函数的完整代码:

void moveSnake()
{

	if (!grow)//如果没有长大,则上次的最后一个点,即尾巴,的地方显示空.这里的grow是在更新食物时我们标记的
	{
		gotoxy(snake.x[snake.len - 1], snake.y[snake.len - 1]);
		printf(" ");//用空格覆盖之前的蛇尾巴
	}
	for (k = snake.len - 1; k>0; k--)//蛇的身子一格一格的移动
	{
		snake.x[k] = snake.x[k - 1];
		snake.y[k] = snake.y[k - 1];
	}
	if (kbhit())//检查当前是否有键盘输入
	{
		ch = getch();
		if (ch == ' ')												//如果输入空格表示暂停,使用while函数一直卡着。
		while (getch() != ' '){};
		if (ch != UP && ch != DOWN && ch != LEFT && ch != RIGHT)	//如果输入的时其他的键,则使用默认方向。这里的UP啊啥的都是之前定义好的
		{
			ch = Direction;
			goto sport;//无条件跳转
		}

		if (Direction != ch)//如果输入的不默认方向
		{
			if ((Direction == UP &&ch != DOWN) || (Direction == DOWN &&ch != UP) || (Direction == LEFT && ch != RIGHT) || (Direction == RIGHT && ch != LEFT)) //Prevent reverse movement
			{//确保输入的方向与当前方向逻辑上不违背,即确保蛇不能倒退
				Direction = ch;
				goto sport;
			}
			else
			{//如果违背了。则保持当前
				ch = Direction;
				goto sport;
			}

		}
		else
		{
			goto sport;
		}
	}
	else
	{
	sport:
		switch (ch)							//移动蛇的头部
		{
		case UP: snake.x[0]--; break;//注意,在窗口中,坐标与我们常用的坐标是倒过来的
		case DOWN:  snake.x[0]++; break;
		case LEFT: snake.y[0]--; break;
		case RIGHT: snake.y[0]++; break;
		default: break;

		}
	}

	gotoxy(snake.x[0], snake.y[0]);
	printf("@");							//输出蛇的头
	grow = 0;//把grow标记回0
	gotoxy(FRAME_HEIGHT, 0);//把光标始终弄在结尾处
}

emm,为了方便大家理解,我在它原本的基础上加了不少注释,方便大家理解。

isAlive函数

这个函数时用来判断蛇是否存活。主要的逻辑是判断蛇是否撞到边界和撞到自己。
这个函数很简单,就是一个判断函数

int isAlive(void)
{//判断蛇是否还活着,即判断蛇有没有撞上自己的身体,有没有碰到边界
	if (snake.x[0] == 0 || snake.x[0] == FRAME_HEIGHT - 1 || snake.y[0] == FRAME_WIDTH - 1 || snake.y[0] == 0)   //When you touch a wall or eat your own body, you die
		return 0;
	for (k = 1; k<snake.len; k++)
	if (snake.x[k] == snake.x[0] && snake.y[k] == snake.y[0])
		return 0;
	return 1;
}

getSpeed函数

这个函数是用来根据蛇的长度判断蛇的速度的。但是我们主要的速度逻辑并不是在这里实现的,所以这个函数并不复杂。

void getSpeed(void)//根据长度修改速度
{
	if (snake.len <= 6)
		snake.speed = 200;
	else if (snake.len <= 10)
		snake.speed = 175;
	else if (snake.len <= 20)
		snake.speed = 150;
	else if (snake.len <= 30)
		snake.speed = 100;
	else snake.speed = 50;
	if (snake.len == 40)
		finish = 0;//长度40为通关
}

main主函数

嘿嘿,关于snake.h和它的函数终于写完了。接下来我们就可以来完成最后一步了。之前说了,我们只要在开头把snake.h的头文件包含进来,就可以直接用了。具体逻辑我就不详细讲解了,但是注释我还是给大家打的挺详细的。在这里插入图片描述

#include "snake.h"
#include <windows.h>
#include <math.h>
//Transposed structure object
extern  struct Food food;//全局变量申明
extern  struct Snake snake;

//main function
int main()
{
	ret = menu();//显示初始化菜单,并且判断用户是否想玩游戏
	if (ret == 1)//输入1,表示是
	{
		while (finish)
		{
			initMap();																	//初始化地图
			while (TRUE)
			{
				updataFood();														//updata food
				getSpeed();															//speed
				moveSnake();														//move snake
				Sleep(snake.speed);	//是计算机处理的程序的函数。。功能是暂停,单位是毫秒,它就是用来控制蛇的快慢的,嘿嘿。其实就是通过这个函数让系统进程变慢,从而控制蛇的快慢
				printFont(FONT_WINDOW_STARTX, FONT_WINDOW_STARTY, snake.speed);		//显示游戏信息
				if (!(isAlive()))//如果没有存活,则结束
					break;
			}
			if (finish)//如果没有标记通关,则显示你这次的长度														//Death or customs clearance
			{
				system("cls");//清屏函数
				gotoxy(22, 5);
				printf("您的游戏结束,您操作的贪吃蛇长度为%d,请再接再厉",snake.len);
				gotoxy(24, 5);
				printf("按(1)键退出游戏,按(2)键重玩");
                char ch;
                while((ch=getch(),ch)!= 50)
                {
                    if(ch==49) return 0;
                    if(ch==50) break;
                }
				system("cls");
			}
			else//如果通关了
			{
				system("cls");
				gotoxy(22, 5);
				printf("恭喜你通关了");
				gotoxy(24, 5);
				printf("按(1)键退出游戏,按(2)键重玩");
                char ch;
                while((ch=getch(),ch)!= 50)
                {
                    if(ch==49) return 0;//注意这里的49没有引号,是数字,因为“1”的ASIIC码值就是49,所以可以这样判断
                    if(ch==50) break;
                }
				system("cls");
			}

		}

	}
}

关于贪吃蛇这个小项目的讲解就到这里了,大家可以自己去尝试下,完善下。其实在实际的写课设的过程中,写的顺序并不是我这个讲解的顺序,我只是为了方便大家理解。写过课设的童鞋都知道,大多都是自己先定一个大概的框架,然后再逐步完善的而不是像这个一样一口气写出来。
最后,大家如果有不明白的地方也欢迎在评论区问我。也可以来技术菌团的qq群一起讨论

发布了26 篇原创文章 · 获赞 20 · 访问量 3458

猜你喜欢

转载自blog.csdn.net/qq_44886056/article/details/104210057