贪吃蛇游戏的C语言实现

题目 贪吃蛇 程序说明

一功能实现

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

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

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

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

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

二 流程图

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

三 程序分析

链表头是蛇尾

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

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”>…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值