贪吃蛇游戏的C语言实现

题目 贪吃蛇 程序说明

一功能实现

1.贪吃蛇正常的移动,wsad控制上下左右移动。

2.贪吃蛇每吃一个食物增长1格,分数加1.

3.分数每增加5分,食物数量增加一个。食物时间可以为20,30,40.分数随时间变化而变化。

4.空格为暂停,F可以加速5格。P为退出并保存。

5.蛇头碰墙,碰身体,反方向都视为死亡。

二 流程图

Created with Raphaël 2.2.0 开始 数据初始化 (食物,蛇身), 如果以前数据将以前数据还原 没有则初始化数据 是否撞墙,以及撞身体 结束 是否吃到食物 蛇身体增加一个节点,增加到蛇头 (相当于移动一次) 显示食物,蛇身,每一秒清屏一次 蛇移动 yes no yes no
Created with Raphaël 2.2.0 开始 从键盘获取方向 将键盘指令发 送给主程序 如何键盘输入“q”, 保存数据并退出 结束 yes no

三 程序分析

链表头是蛇尾

1.创建链表,蛇的与食物的初始化

扫描二维码关注公众号,回复: 5560070 查看本文章
struct foood_node *fcreat_link(int m)				//m的创建是为了后面食物的增加以及数据保存做准备,开始时为1
{
	srand(time(NULL));
	struct food_node *p,*ptail;
	int i;
	for(i=0;i<m;i++)
	{
		p = (struct food_node *)malloc(sizeof(struct food_node)); 			//创建一个节点
		if(p == NULL)
		{
			free(fhead);
			printf("failure\n");
			return NULL;
		}
		p->date.x = rand()%38 + 21;			//赋初值(根据边框坐标来定)
		p->date.y = rand()%19 + 6;
		p->date.time = (rand()%3+2)*10;
		if(i == 0)
			fhead = p;
		else
			ptail->next = p;
		ptail = p;
		p->next = NULL;
	}
}

struct snake_node *creat_link(int n)			//n的创建是为了后面蛇的身体增加以及数据保存做准备,开始时为3
{
	struct snake_node *p,*ptail;
	int i;
	for(i=0;i<n;i++)
	{
		p = (struct snake_node *)malloc(sizeof(struct snake_node));			//创建一个节点
		if(p == NULL)
		{
			free(head);
			printf("failure\n");
			return NULL;
		}
		p->date.x = 30+i;
		p->date.y = 15;
		p->date.dir = RIGHT;
		if(i == 0)
			head = p;
		else
			ptail->next = p;			//将邻近的节点连起来
		ptail = p;
		p->next = NULL;
	}
}

结构体定义见程序,此处不详解释

2.蛇的移动
将蛇身体的每一个节点依次将后一个结点的数据赋给前边的,并对最后一个数据判断此时方向对其作相应的操作,上下Y±1,左右 X±1;

p = head;
		while(p!= NULL && p->next!=NULL)
		{
			p->date.x = p->next->date.x;			//将每个节点的数据依次往后赋值;
			p->date.y = p->next->date.y;
			p->date.dir = p->next->date.dir;

			p = p->next;
		}
		if(cur_dir == RIGHT || cur_dir == LEFT)
			p->date.x += (cur_dir-3);			
		else
			p->date.y += cur_dir;
		p->date.dir = cur_dir;
	

3.蛇的增长
获得蛇头的下次节点位置(将来时);

	while(p!= NULL && p->next!=NULL)			//获得链表尾的节点数据,及蛇头的数据
		p = p->next;

	if(cur_dir == RIGHT || cur_dir == LEFT)			//将蛇头的数据根据当前的方向进行移动操作
	{																		
		q.date.x = p->date.x + (cur_dir-3);
		q.date.y = p->date.y;
	}
	else
	{
		q.date.x = p->date.x;
		q.date.y = p->date.y + cur_dir;
	}

判断蛇头及链尾的下一次位置(将来时)与食物的坐标进行比较,如果相等,则创建一个结点将 将来时的数据赋予,并将其连到链尾。不相等继续移动(判断时蛇不移动)。

pnew = (struct snake_node *)malloc(sizeof(struct snake_node));   //如果将来时的蛇头与食物坐标相同,那么创建一个节点,节点数据与将来时数据(食物坐标)相同,
		pnew->date.x = q.date.x;						//相等时,此时蛇不进行移动操作
		pnew->date.y = q.date.y;
		pnew->date.dir = cur_dir;
		p = head;
		while(p!=NULL)
		{
			pold = p;
			p = p->next;
		}
		pold->next = pnew;
		pnew->next = p;

4.食物的增加

食物采用的是链表,所以和蛇的增加相似

struct food_node *pnew,*pold,*p = fhead;
	if(score%5 == 0)
	{
		foodlength++;
		pnew = (struct food_node *)malloc(sizeof(struct food_node));
		pnew->date.x = rand()%38 + 21;
		pnew->date.y = rand()%19 + 6;
		p->date.time = (rand()%3+2)*10;
		p = fhead;
		while(p!=NULL)
		{
			pold = p;
			p = p->next;
		}
		pold->next = pnew;
		pnew->next = p;
	}

5.数据的保存于读取

1.保存

将版本,状态量,蛇的各个节点数据,食物节点数据,分数,蛇的长度,写入一个文件中,(注意格式);

fp = fopen("snake.dat","w");			//打开一个文件,以读的形式打开
	if(fp == NULL)
	{
		perror("open write error");
		return;
	}
	fwrite("SNAKEA",6,1,fp);					//版本名
	fwrite(&ver,4,1,fp);							//版本序数
	fwrite(&snakelength,4,1,fp);			//蛇的长度
	fwrite(&score,4,1,fp);·						//分数
	p = head;
	while(p!= NULL)							//蛇的每个节点数据
	{
		fwrite(&p->date,sizeof(struct snake_date),1,fp);
		p = p->next;
	}
	fwrite(&foodlength,4,1,fp);		//食物长度
	q = fhead;
	while(q != NULL)						//食物的每个节点数据
	{
		fwrite(&q->date,sizeof(struct food_date),1,fp);
		q = q->next;
	}
	fclose(fp);

2.读取要与写时顺序一致,(注意格式)

fread(&ver,4,1,fp);
				if(ver == 1)
				{
					int i;
					struct snake_node *p;
					struct snake_date date1;
					struct food_node *q;
					struct food_date date2;	
					fread(&n,4,1,fp);
					snakelength = n;
					fread(&score,4,1,fp);
					creat_link(snakelength);				//读取蛇的长度
					p = head;
					for(i=0;i<n;i++)							//根据蛇的长度创建相同长度的链表
					{
						fread(&date1,sizeof(struct snake_date),1,fp);
						p->date = date1;
						cur_dir = p->date.dir;
						p = p->next;
					}
					fread(&m,4,1,fp);
					foodlength = m;
					fcreat_link(foodlength);
					q = fhead;
					for(i=0;i<m;i++)
					{
						fread(&date2,sizeof(struct food_date),1,fp);
						q->date = date2;
						q = q->next;
					}

6.此处只详解了部分,其余的都比较容易看懂。
还有食物的判断,蛇头的撞墙,撞身体(就是将蛇头与身体的每个节点比较),画表格等(见下面链接可看详细程序);
编写时要仔细,认真,最好能把大纲列一下。

<ahref=“https://gitee.com/wlwcylsf/HKwork.git”>…

猜你喜欢

转载自blog.csdn.net/weixin_44571701/article/details/86547486