C语言,Linux,贪吃蛇游戏

 

//贪吃蛇游戏
#include<curses.h>
#include<stdlib.h>
#include<pthread.h>

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

struct Snake//结构体(链表用)
{
   int row;//行
   int column;//列
   struct Snake *next;  
};

struct Snake *head=NULL;//蛇尾,链表头
struct Snake *tail=NULL; //蛇头,链表尾
int key;//按键
int dir;//方向
int count=0;//计分用
int *pc=&count;//计分用
struct Snake food;

void initFood()//食物初始化
{  
   int x=rand()%19;//随机数
   int y=rand()%19;//随机数

   food.row=x;
   food.column=y;
}

int linkSnake(int i,int j)//蛇显示(gameBorder函数遍历时判断行列所在位置是否有蛇身)
{
   struct Snake *p=head;
   while(p!=NULL){
      if(p->row==i && p->column==j){  
         return 1;
      }
      p=p->next;
   }
   return 0;  
}

int haveFood(int i,int j)//食物显示(gameBorder函数遍历时判断行列所在位置是否有食物)
{
      if(food.row==i && food.column==j){  
         return 1;
      }
   return 0;  
}


void initNcurses()//ncurses设置
{
   initscr();//初始化,进入ncurses模式
   keypad(stdscr,1);//设置把受到的特殊键比如方向键,转化为ncurses定义的以KEY开头的数字宏(如:向上KEY_UP)。
  // noecho();//界面异常显示时用
}

void gameBorder()//游戏界面显示
{
   int row;
   int column;
   
   move(0,0);//让界面不移动
   
   for(row=0;row<20;row++){
       if(row==0){
           for(column=0;column<20;column++){
              printw("--");
           }
           printw("\n");
       }
       if(row>=0 && row<=19){
           for(column=0;column<=20;column++){
              if(column==0 || column==20){
                  printw("|");  
              }else{
                  if(linkSnake(row,column)){
                      printw("[]");//蛇身
                   }else if(haveFood(row,column)){
                          printw("##");//食物  
                   }else{
                        printw("  "); 
                   }
              }
           }
           printw("\n");
        } 
       if(row==19){ 
           for(column=0;column<20;column++){
              printw("--");
           }
           printw("\nBy Leijiantao KEY \n");
           printw("count= %d", count);
        }
    } 
  
}

void addNode()//按下方向键,蛇头增加,即蛇向前的效果
{
   struct Snake *new;
   new=(struct Snake*)malloc(sizeof(struct Snake));
   new->next=NULL;
   
   switch(dir){
      case UP:
          new->row=tail->row-1;
          new->column=tail->column;
          break;
      case DOWN:
          new->row=tail->row+1;
          new->column=tail->column;
          break;
       case LEFT:
          new->row=tail->row;
          new->column=tail->column-1;
          break;
       case RIGHT:
          new->row=tail->row;
          new->column=tail->column+1;
          break;
   }
  
   tail->next=new;
   tail=new;
}

void initSnake()//初始化蛇及食物
{
   dir =RIGHT;
   struct Snake *p;
   while(head!=NULL){
      p=head;
      head=head->next;
      free(p);
   }
   initFood();//初始化食物
   head=(struct Snake*)malloc(sizeof(struct Snake));
   head->row=1;
   head->column=1;
   head->next=NULL;
   
   tail = head;
   
   addNode();
   addNode();
   addNode();
   addNode();
}

void deleteSnake()//删除蛇尾,即蛇向前的效果
{
   struct Snake *p=head;
   head=head->next;
   free(p);
}

int ifSnakeDie()//判断蛇死亡
{
    struct Snake *p=head;
    if(tail->row<0 || tail->column==0 || tail->row==20 || tail->column==20){ //撞边界死亡
      return 1;
   }
   while(p->next!=NULL){  //头碰到尾死亡(吃到自己死亡)
      if(p->row==tail->row && p->column==tail->column){
         return 1;
      }        
      p=p->next;     
   }
   return 0;
}

void moveSnake()//蛇移动
{   
   addNode();
   if(haveFood(tail->row,tail->column)){//吃到食物蛇尾不删(即蛇变长)
       initFood();//食物位置变化
       count++;//得分
   }else
   deleteSnake();
   if(ifSnakeDie()){//如果蛇死亡
      initSnake();//重新开始
      *pc=0;//得分清零
   }
}

void* refreshBrench()//刷新界面
{
   while(1){   
         moveSnake();
         gameBorder();
         refresh();//我们写入的内容首先会在系统缓冲区中,经过refresh()函数刷新之后才能够显示到屏幕上。
         usleep(100000);//延时100000微秒usleep(微秒),sleep(秒)。
   }
}

void turn(int direction)//确保蛇不后退
{
    //绝对值判断,比如目前是UP(=1),按下向下键DOWN(=-1),UP的绝对值=DOWN的绝对值,dir不等于输入的DOWN,继续执行UP。
    //当按RIGHT或LEFT时,UP的绝对值!=RIGHT或LEFT的绝对值,执行dir = direction; 即执行输入的RIGHT或LEFT。
    if(abs(dir)!=abs(direction)){  
        dir = direction;
    }
}

void* changeDir()//按方向键,改变方向
{
   key=getch();
   while(1){
      key= getch();
      switch(key){
          case KEY_DOWN:
             turn(DOWN);
             break;
          case KEY_UP:
             turn(UP);
             break;
          case KEY_LEFT:
             turn(LEFT);
             break;
          case KEY_RIGHT:
             turn(RIGHT);
             break;
       }
    }
}

int main()
{
   pthread_t t1;
   pthread_t t2;
  
   initNcurses();
   initSnake();
   gameBorder();
   
   //线程,refreshBrench、changeDir两个函数同时执行
   pthread_create(&t1,NULL,refreshBrench,NULL);
   pthread_create(&t2,NULL,changeDir,NULL);
   
   while(1);//主程序循环不退出
   getch();//停顿
   endwin();//退出ncurses模式
   return 0;
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值