简易贪吃蛇(c语言实现)

简易贪吃蛇(c语言实现)

#include<ncurses.h>//读取键盘输入的库
#include<stdlib.h>//malloc 动态分配的库
#include<locale.h>//显示汉字的库
#include<unistd.h>//usleep延时函数库
#include<pthread.h>//多线程的库

#define UP     1//宏定义
#define DOWN  -1
#define LEFT   2
#define RIGHT -2

void add();
void dtshe();
void cshshiwu();
int flag=0;//赵的标记全局变量
int key;//方向标记位
int dir;//控制蛇的方向
struct da//定义结构体,创建链表
{
	int hang;
	int lie;
	struct da *next;
};
struct da *head=NULL;
struct da *tail=NULL;
struct da food;
void chushihua()//贪吃蛇初始化函数
{
	initscr();
        keypad(stdscr,1);//ncurses初始化
	noecho();//防止显示功能键导致乱码
	dtshe();//初始化一条蛇
	cshshiwu();
}
int pdd(struct da *she)//判断蛇的死亡函数
{
        struct da *p=(struct da*)malloc(sizeof(struct da));
        p=she;
        while(p->next!=NULL)
	{
                if(p->hang==tail->hang&&p->lie==tail->lie)//如果撞到自己则回到开始的状态
		{
			return 1;
		}
		if(tail->hang==0||tail->hang==20||tail->lie==0||tail->lie==20)//如果撞墙则初始化,回到刚开始的状态
        	{
                	return 1;
	        }
                p=p->next;//移动到下一个节点
        }
	return 0;
}
void cshshiwu()//初始化食物
{
	int x=rand()%20;//静态局部变量使用static修饰符定义,即使在声明时未赋初值,编译器也会把它初始化为0。且静态局部变量存储于进程的全局数据区,即使函数返回,它的值也会保持不变。
	int y=rand()%20;
	food.hang=x;
	food.lie=y;
}
int sw(int hang,int lie)//输出食物函数
{
	if(hang==food.hang&&lie==food.lie)
        {
		return 1;
        }
}
int tcs(int hang,int lie,struct da *she)//显示函数,如果传入的行列与she对应的相等,首先输出赵,然后一直输出皮
{
	struct da *p=(struct da*)malloc(sizeof(struct da));
	p=she;
	while(p!=NULL)
	{
		if(hang==p->hang&&lie==p->lie)
		{
			if(flag==0)//第一次进入返回2,后面一直返回1
			{
				flag=1;
				return 2;
			}
			else
			{
				return 1;
			}	
		}
		p=p->next;//移动到下一个节点
	}
}
void dtshe()//初始化贪吃蛇函数
{
	dir=LEFT;//初始化蛇的方向
	while(head!=NULL)//如果不是第一次调用这个函数,则释放掉之前建立的蛇
	{
		struct da *sf;
		sf=head;
		head=head->next;
		free(sf);
	}
	head=(struct da*)malloc(sizeof(struct da));
        head->hang=1;
        head->lie=19;
	head->next=NULL;
	tail=head;//开始时,头节点和尾节点内存地址是一个地址,然后tail后面接节点就在这个地址后面接,所以连上了
	add();//增加蛇身子节点
	add();
	add();
	add();
}
void add()//控制蛇的移动方向以及增加蛇身子函数
{
	struct da *new=(struct da*)malloc(sizeof(struct da));
	new->next=NULL;
	switch(dir)
	{
		case RIGHT:
			new->hang=tail->hang;
			new->lie=tail->lie+1;
			break;
                case LEFT:
                        new->hang=tail->hang;
                        new->lie=tail->lie-1;
			break;
                case UP:
                        new->hang=tail->hang-1;
                        new->lie=tail->lie;
			break;
                case DOWN:
                        new->hang=tail->hang+1;
                        new->lie=tail->lie;
			break;
	}
	tail->next=new;
	tail=new;//尾节点等于新节点
}
void shuchu()//输出函数
{
	move(0,0);//初始化光标位置
	int hang;
        int lie;
	for(hang=0;hang<=20;hang++)
        {
                for(lie=0;lie<=20;lie++)
                {
                        if(hang==0&&(lie!=0&&lie!=20)||hang==20&&(lie!=0&&lie!=20))//打印地图
                        {
                                printw("[]");
                        }
                        else if(lie==0||lie==20)
                        {
                                printw("[]");
                        }
                        if(hang!=0&&hang!=20&&lie!=0&&lie!=20)
                        {
                                if(tcs(hang,lie,head)==2)//这里不能调换位置,调换位置之后tcs第二次调用返回1会影响结果
                                {
                                        printw("赵");
                                }
                                else if(tcs(hang,lie,head)==1)
                                {
                                        printw("皮");
                                }
				else if(sw(hang,lie)==1)
				{
					printw("皮");
				}
                                else
                                {
                                        printw("  ");
                                }
                        }
                        if(lie==20)
                        {
                                printw("\n");
                        }
                }
        }
        printw("作者:赵皮皮\n");
        printw("欢迎加入电子设计工作室\n");
}
void delete()//头节点向后移动
{
	head=head->next;
}
void youyd()//改变蛇移动方向的函数
{
	add();//增加一个新节点
	if(sw(tail->hang,tail->lie)==1)
	{
		cshshiwu();
	}
	else
	{
		delete();//删除一个旧节点
	}
	if(pdd(head))//如果撞墙或者撞到自己则初始化,回到刚开始的状态
	{
		dtshe();
	}
}
void* yidong()//移动函数,每隔100微秒重新打印地图
{
	while(1)
	{
		youyd();//改变蛇的方向
		flag=0;//每次执行,让标记置0,目的输出赵
	        shuchu();//打印地图函数
	        refresh();//刷新函数
		usleep(100000);//延迟函数,100微秒
	}
}
void turn(int direction)//防止反向移动函数
{
	if(abs(dir)!=abs(direction))
	{
		dir=direction;
	}
}
void* shuru()//读入键盘数值,确定移动方向函数
{
	while(1)
	{
		key=getch();//读入键盘输入,确定方向
		switch(key)
		{
			case KEY_RIGHT:
				turn(RIGHT);
				break;
			case KEY_LEFT:
                	        turn(LEFT);
                      		break;
			case KEY_UP:
	                        turn(UP);
	                        break;
			case KEY_DOWN:
        	                turn(DOWN);
                	        break;
		}
	}
}
int main()
{
	setlocale(LC_ALL,"");//显示中文
	pthread_t th1;//定义多线程
	pthread_t th2;
	chushihua();//调用初始化函数
	pthread_create(&th1,NULL,shuru,NULL);
        pthread_create(&th2,NULL,yidong,NULL);
	while(1);
	endwin();//结束函数
	return 0;
}
//总体思路:采用多线程的方式,让键盘输入函数和打印整个贪吃蛇游戏的函数同时进行,当键盘读入数值时通过方向标记变量结合移动函数使蛇移动
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值