C语言学习第11次打卡-贪吃蛇

贪吃蛇项目

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <curses.h>
#include <pthread.h>
#include <time.h>

struct snake {
int hang;
int lie;
struct snake *next
};

struct snake *head=NULL;
struct snake *tail=NULL;
struct snake *food=NULL;

int foodsigal=0;//吃食信号
int dir=0;//保持运动方向数据
//下面互锁数据
int ddata=0;
int udata=0;
int ldata=0;
int rdata=0;

void initcurse()//Ncurse初始化
{ initscr();
  keypad(stdscr,1);
}

void addsnake() //每用到一次给蛇添加一个行的节点
{
struct snake *pfstruct=head;//(struct snake*) malloc(sizeof(struct snake));
//pfstruct=head;  //制造一个分身来替代头文件,避免污染头文件。
struct snake *new ;
new=(struct snake*)malloc(sizeof(struct snake)) ;//定义新的结构体指针
while (pfstruct->next!=NULL)
{
pfstruct=pfstruct->next;
}

if(pfstruct->next==NULL){  //每次定位到链表的尾巴,
new->hang=pfstruct->hang;
new->lie=pfstruct->lie+1;
new ->next=NULL;
pfstruct->next=new;//追踪到尾巴之后,把尾巴的位置传递给NEW。
tail=new;
}
}

void makesnake(int ls)//定义起始蛇的长度。
{head=(struct snake*) malloc(sizeof(struct snake));
   head->hang=2;
   head->lie=2;
   head->next=NULL;

int i=0;
for(i=0;i<ls-1;i++)
{
addsnake();
}
}

void dlsnake()//蛇身的删除,每进行一次删除蛇的头
{
 head=(head)->next;
  //更改后的头还是head;
}

int  foodeat(){
   if(tail->hang==food->hang&&tail->lie==food->lie)
   {
       return 1;// 反馈用于蛇身
   }
   else {return 0;}
}

int foodfunc(int hang,int lie)//食物的随机产生程序rand函数
{
  if(hang==food->hang&&lie==food->lie){
        return 1;
  }
   else{ return 0;}
}


int isnake(int hang,int lie )//对蛇身的链表做一个判断
{
struct snake *slink=(struct snake*)malloc(sizeof(struct snake)) ;
slink=head;
  while(slink!=NULL)//对整个链表进行对比
  {
    if(slink->hang==hang&&slink->lie==lie)
    {
      return 1;
    }
    slink=slink->next;
  }
  return 0;
}

void mapsetup(void)//地图产生规则,产生一个正方形的框架
{
 int data1,data2;
 int hang=0;
 int lie =0;
 move (0,0);
 for (hang=0;hang<20;hang++){
   
    if (hang==0||hang==19) {
       for (lie=0;lie<20;lie++)
            {printw("--");   }
     }
    if(hang>0&&hang<19){

       for (lie=0;lie<=20;lie++)
       {
 
          if(lie==0||lie==20)
                  {printw("|");}

		  if(lie>0 && lie<20){
 data1=isnake(hang,lie);data2=foodfunc(hang,lie);
                     if(data1==1||data2==1){  
		         if(data1)//每次只要链表的行列对的上,就产生一个蛇身。
		             { printw("[]");} 
                         if(data2)//判断产生食物,mapsetep函数调用foodfunc程序,foodfunc程序调用ifeat程序。
                             { printw("##");}
                     }
                      else
                            {printw("  ");}
                      }
		  }
	       } 
	    
	     printw("\n");
	 }
	}

int  eatself(){
  struct snake *phead=head;
      while(phead->next!=NULL){
           if(phead->hang==tail->hang&&phead->lie==tail->lie)
              {return 1;}
            
            else{ phead=phead->next;}
           }
      return 0;
  
}

void ifdiedo()//死亡规则,撞墙和自食
{
         int  data=eatself();
         struct snake *head1=(struct snake *)malloc(sizeof(struct snake));
         head1=head;
         struct snake *head2;
	 if(data==1||tail->hang==0||tail->hang==20||tail->lie==0||tail->lie==20){
	   {
	       while(head1!=NULL){//清除缓存,防止过载
	       head2=head1;
	       head1=head1->next;
               free(head2);
               }
              dir=0;//清除原来的运动方向           
              makesnake(4);//重新设定蛇的长度,位置
             //下面清除互锁
              ddata=0;
              udata=0;
              ldata=0;
              rdata=0;

           }
}
}
void movesnake()//判断蛇的下一步行动
{
if(dir==3||dir==4||dir==5||dir==2){
switch(dir){   //顺序上下左右
case 3:{
struct snake *new1=(struct snake *)malloc (sizeof(struct snake));
new1->hang=tail->hang-1;
new1->lie=tail->lie;
new1->next=NULL;
tail->next=new1;///
tail=new1;
break;}
case  2:{
struct snake *new2=(struct snake *)malloc (sizeof(struct snake));
new2->hang=tail->hang+1;
new2->lie=tail->lie;
new2->next=NULL;
tail->next=new2;///
tail=new2;
break;
}
case  4:{
struct snake *new3=(struct snake *)malloc (sizeof(struct snake));
new3->hang=tail->hang;
new3->lie=tail->lie-1;
new3->next=NULL;
tail->next=new3;///

tail=new3;
break;
}
case  5: {
struct snake *new4=(struct snake *)malloc (sizeof(struct snake));
new4->hang=tail->hang;
new4->lie=tail->lie+1;
new4->next=NULL;
tail->next=new4;
tail=new4;///
break;
}
  }}
  else { 
    addsnake();
  }

if (foodeat())//吃到食物返回0,不删除。
{
      food->hang=rand()%18+1;
      food->lie=rand()%19+1;
      food ->next=NULL;
  struct snake *phead=head;
  while(phead!=NULL){//食物和蛇身重合则重新产生食物
    if(phead->hang==food->hang&&phead->lie==food->lie){
      food->hang=rand()%18+1;
      food->lie=rand()%19+1;
      food ->next=NULL;
      phead=head;
     }
    else{phead=phead->next;}
  }
}
else{dlsnake();} 
}

void *func1(){
 int data=0;
   while(1){
       data=getch();
//用if语句进行互锁,不能做方向相反的运动
       switch (data){
           case 0402:
if(ddata==0)
{
udata=1;
ldata=0;
rdata=0;
           dir=2;
}
           break;
           case 0403:
if(udata==0)
{
ddata=1;
ldata=0;
rdata=0;
           dir=3;
}
           break;
           case 0404:
if(ldata==0)
{
rdata=1;
udata=0;
ddata=0;
           dir=4;
}
           break;
           case 0405:
if(rdata==0)
{          
ldata=1;
udata=0;
ddata=0;
           dir=5;
}
           break;
        }   
    }   
}

void *func2()
{
food->hang=5;
food->lie=5;
food->next=NULL;
  while (1){     //运动->判断死亡->构建画面,包括蛇身和食物。
    movesnake();
    ifdiedo();//再每次前进一步的时候都做一次死亡判断
     foodeat();
   mapsetup();
    refresh();
    usleep(100000);
  }
}

int  main()
{
food= (struct snake*)malloc(sizeof(struct snake));
pthread_t th1;
pthread_t th2;
  makesnake(4); 
  initcurse();
  mapsetup();
pthread_create(&th1,NULL,func1 ,NULL);
pthread_create(&th2,NULL,func2 ,NULL);
 while(1);
  getch();
  endwin();
  return 0;
}

//60行 initcurse();//发现一个问题只要在initcurse之前设置了代码就会发现有报错:Segmentation fault (core dumped),原因是addsnake函数中用initcurse的函>    数,main函数中在还没声明initcurse函数之前使用了inicurse中的函数,initcusre用于启用Ncurse功能。

通过这个程序对稍微复杂项目有了更系统的认知,正确的项目步骤应该是构建一个程序开始。
对C语言的编程经验也有更细节的了解,对linux系统的操作也更熟练了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值