基于Linux系统下使用ncurese图形库与pthread思想实现贪吃蛇游戏游戏(有详细注解)

废话少说,先上代码!

#include <curses.h>   
#include <stdlib.h>
#include <unistd.h>  
#include <pthread.h> //使用多线程思想实现位移与按键的双运行 

int key;   //用于存放用户输入的方向键的数码 
int dir;   //用于赋值数值 

#define UP 1 
#define DOWN -1
#define RIGHT 2
#define LEFT -2


void initnurses(){ 

   initscr();   //ncurses库初始化

   keypad(stdscr,1);
    noecho();  //告诉curses不要把输入回显到屏幕上 
}

struct snake{  //结构体蛇模块 

    int hang;
    int lie;
    struct snake *next;

};

struct snake *head=NULL; //使用动态链表方式实现尾节点插入,这里设置为头结点 
struct snake *tail=NULL; //使用动态链表方式实现尾节点插入,这里设置为尾结点
struct snake food;      // 结构体表示食物模块 

void initfood(){       //食物初始化 
   int x=rand()%20;    //rand()函数初始化食物x坐标 
   int y=rand()%20;    //rand()函数初始化食物y坐标 

    food.hang = x;
    food.lie = y;
   
}

int hasfood(int i,int j){  //用于判断食物位置是否与尾结点重合 
    if(food.hang==i && food.lie==j){
      return 1;
    }
    else{
    
      return 0;
    }

}

int snake_line(int x,int y){  //判断蛇模块长度判断
 
    struct snake *p;
     p = head;       
    while(p !=NULL){
  
    if(p->hang==x && p->lie==y){
       return 1;
       }

   p=p->next;
    }
    
    return 0;


}




void mapbuilt(){  //地图绘制与食物绘制以及蛇模块绘制 
  int hang,lie;
    move(0,0); //保证更新不会出现新地图 
   
    for(lie=0;lie<=20;lie++){
            if(lie==0 || lie==20){
	  for(hang=0;hang<20;hang++){
               
		  printw("--");
               
	  }
      }
	 

	    else{
      
	  for(hang=0;hang<=20;hang++)
	  {
              if(hang==0 || hang == 20){
	        printw("|");
	      }
	      else if(snake_line(hang,lie)){
	      
	        printw("[]");
	      
	      }

              else if(hasfood(hang,lie)){
	      
	        printw("##");
	       
	      }
       
	      else{
	        printw("  ");
	      }
	  }
      }
	 
	   printw("\n");
  }
 printw("make by lhy==food.hang:%d,food.lie:%d\n",food.hang,food.lie);  //显示食物坐标位置 
}


void add_snake(){ //增加蛇模块,此外还可以控制蛇的左右上下移动 
  struct snake *new;
  new=(struct snake *)malloc(sizeof(struct snake)); //malloc函数开辟新空间 
   

    switch(dir){
	    case UP:
                new->hang = tail->hang; 
                new->lie  = tail->lie-1;
		break;
           case DOWN:
                new->hang =tail->hang; 
	      	new->lie  = tail->lie+1;
		break;
           case RIGHT:
		new->hang = tail->hang+1;
		new->lie = tail->lie;
		break;
	   case LEFT:
		new->hang = tail->hang-1;
                new->lie  = tail->lie;
		break;
    }

  new->next =NULL;
  
  tail->next = new;
  tail = new;


}




 
void init_snake(){  //初始化蛇模块,表示蛇模块为x=2,y=2. 

    struct snake *p;
     while(head != NULL){// 当蛇死亡,重新生成新的蛇,应当及时清理之前的链表,防止时间一长导致内存泄露 
	     p=head;
        head = head->next;
	free(p);
     
     }

  
   initfood();
   head =(struct snake *)malloc(sizeof(struct snake)); //开始内存,先形成头结点,不够使用的是尾插法 
   head->hang=2;
   head->lie=2;
   head->next=NULL;

   tail=head; 
   dir=RIGHT;//start go right

   add_snake();
   add_snake();
   add_snake();
   add_snake();
}


void delar_snake(){ // 删除蛇的长度,保证陕西中医药大学移动长度一样 

    struct snake *p;
    p=head;

    head = head->next;
    free(p);

}


void movesnake(){ //实现碰壁死亡,与吃的食物蛇长度增长 
      
   add_snake();
   if(hasfood(tail->hang,tail->lie) ){
  // if(tail->hang==food.hang && tail->lie==food.lie ){
        initfood();
   }else{

  delar_snake();
      
  }
   if(tail->hang==0 || tail->lie==0 || tail->hang==20 || tail->lie==20){
   
        init_snake();
   }
}

void turn(int dirction){ //绝对值设置,防止蛇可以通知左右移动(那不然会很酷) 
     if(abs(dir) != abs(dirction)){
        
        dir = dirction;
     }


}


void* choosewhere(){ //赋值ncurses库的上下左右移动的按键数码 
   
	while(1){
     key=getch();
    switch(key){
       case KEY_DOWN:
    	        turn(DOWN);
            break;
       case KEY_UP:
	        turn(UP);
	    break;
       case KEY_RIGHT:
	        turn(RIGHT);
	    break;
       case KEY_LEFT:
	        turn(LEFT);
	    break;
      }   
    }
}

void* refreadsnake(){  //蛇移动,在Linux系统下 usleep可以控制蛇速度,单位为us,sleep()单位为s 
  while(1){
     movesnake();
     mapbuilt();
     refresh();     //更新 
     usleep(100000); //0.1s 
    
  }

}



int main(){
   
   initnurses(); 
   init_snake(); 
  pthread_t th1;  
  pthread_t th2; 
 
    mapbuilt();
   pthread_create(&th1, NULL, choosewhere, NULL); // 线程1创立 ,表示方向选择 
   pthread_create(&th2, NULL, refreadsnake, NULL);// 线程2创立 ,表示蛇移动 
  
  while(1);  //保证线程一直运行 
   getch();  //防止程序退出 
   endwin();


   return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值