bboarr 2021-07-26 14:38 采纳率: 50%
浏览 92
已结题

linux下用c语言编写贪吃蛇小游戏出现问题

生成的可执行文件./step 结果贪吃蛇不移动,如图所示:

img

大致判断是snakeMove()函数出现问题
请教代码哪里出现问题,自己无法找到。
以下是全部代码:
head.h

#include<stdio.h>
#include<termios.h>
#include<stdlib.h>
#include<signal.h>
#include<time.h>
#include<string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <signal.h>
#include <sys/time.h>


//界面大小
#define WallX 55
#define WallY 20

#define U 1
#define D 2
#define L 3
#define R 4

//所有结构体的定义
struct termios tm_old;   //键盘返回值不显示
typedef struct snake {
    int x;
    int y;
    struct snake *next;
}snake;

//定义全局变量

int status;

snake *head ;
snake *food ;//蛇头指针,食物指针 
snake *q ;//遍历蛇的时候用到的指针 



//所有函数的声明
void jiemian();          //显示刚进入开始界面函数
void interface();        //刚进入界面操作函数
int getch();             //键盘返回值不显示函数
void creatMap();         //游戏界面创建函数
void initSnake();        //初始化蛇身,并打印出来   
void creatFood();        //随机出现食物函数
void snakeMove();        //蛇移动
void cantCrossWall();    //不让穿墙
void endGame();          //中止游戏
int biteSelf();         //咬到自己
void runGame();
//判断是否有按键按下
int kbhit(void);
int getch();
void alarm_us(int n);


interface.c

#include"head.h"
int kbhit(void)
      {
          struct termios oldt, newt;
          int ch;
          int oldf;
          tcgetattr(STDIN_FILENO, &oldt);
          newt = oldt;
          newt.c_lflag &= ~(ICANON | ECHO);
          tcsetattr(STDIN_FILENO, TCSANOW, &newt);
          oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
          fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
          ch = getchar();
          tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
          fcntl(STDIN_FILENO, F_SETFL, oldf);
          if(ch != EOF)
          {
              ungetc(ch, stdin);
              return 1;
          }
          return 0;
      }

int getch()
{
    struct termios tm;
    tcgetattr(0,&tm_old);
    cfmakeraw(&tm);
    tcsetattr(0,0,&tm);
    int ch = getchar();
    tcsetattr(0,0,&tm_old);
    return ch;
}
void interface(){
    int ch = getch();
    
    
        if(ch == 48){
            endGame();
        }
        if(ch == 49)
        //开始游戏
        {
            creatMap();
                initSnake();
            creatFood();
            runGame();

        }
           
    
     
}

void jiemian(){
           printf("---------------------------------------\n");
        printf("|           SNAKE 小游戏              |\n");
    printf("|           按1.开始游戏              |\n");
    printf("|           按2.游戏说明              |\n");
    printf("|           按3.游戏设置              |\n");
    printf("|           按4.查看排行榜            |\n");
    printf("|           按0.退出                  |\n");
    printf("---------------------------------------\n");

}
int main(){
    jiemian();
    interface();
    
    return 0;
}

creatMap.c

include"head.h"
void creatMap()
{
    //打印边框
    int i;
    for(i=0;i<=WallX;i++)//打印上下边框
    {
        printf("\033[%d;%dH\033[43m \033[0m\n",10,i+10);
                 //设置坐标   设置颜色     传递参数
           }
    for(i=0;i<=WallX;i++)
    {
        printf("\033[%d;%dH\033[43m \033[0m\n",WallY+10,i+10);
    }

           for(i=0;i<WallY;i++)//打印左右边框
    {
               printf("\033[%d;%dH\033[43m \033[0m\n",i+10,10);
         
    } 
    for(i=0;i<WallY;i++)
    {
        printf("\033[%d;%dH\033[43m \033[0m\n\n",i+10,WallX+10);
    }

}

initsnake.c

#include"head.h"

snake *tail;     //蛇尾指针



//初始化蛇的身体
void initSnake()
{
    //从蛇尾开始,头插法,以x y设定开始的位置
    tail = (snake*)malloc(sizeof(snake));
    tail->x=20;
    tail->y=15;
    tail->next=NULL;
    for(int i=1;i<=4;i++)//蛇初始长度为4
    {
        head=(snake*)malloc(sizeof(snake));
        head->next=tail;
        head->x=20+i;
        head->y=15;
        tail=head;
    //表面上是把head指针的值赋给了tail
    //其实是把tail节点的指针域指向了最后一个head节点    
    }
    //所以这一步才能遍历整个蛇链表
    //意思是当头节点的指针域指向的下一块内存不是NULL的时候
    //(通俗的讲是头节点的下一个节点不为空)
    while(tail!=NULL)
    {
        printf("\033[%d;%dH\033[47m \033[0m\n",tail->y,tail->x);
    //相当与这一步,让在23行已经指向头节点的tail节点作为头节点
    //开始遍历蛇链表,直到遍历到蛇尾节tail->next=NULL时
        tail = tail->next;
    }

}

creatFood.c

#include"head.h"

void creatFood()
{
    snake *food1;
    //为了防止每次产生的随机数相同,种子设置为time(NULL)
    srand((unsigned)time(NULL));
    food1 = (snake*)malloc(sizeof(snake));
    //food的范围是: 1.多少就对范围的max+min取余  2.min
    //在对food进行判断之前,先对其进行初始化
    food1->x = rand()%54+11;
    while((food1->x%2)!=0)
    {
        food1->x = rand()%54+11;
    }
    food1->y = rand()%19+11;
    q=head;
    while(q)
    {
        //判断蛇身是否与食物重合
        if(q->x==food1->x&&q->y==food1->y)
        {
            free(food1);
            food1=NULL;
            creatFood();
            return ;
        }
        q=q->next; //遍历蛇身
    }
    printf("\033[%d;%dH\033[43m \033[0m\n",food1->y,food1->x);
    food = food1;


}

runGame.c

#include"head.h"

void alarm_us(int n)
      {
                   struct itimerval value;
                    //定时器启动的初始值
                         value.it_value.tv_sec = 0;
                     value.it_value.tv_usec = n;
                      //定时器启动后的间隔时间值
                           value.it_interval.tv_sec = 0;
                       value.it_interval.tv_usec = n;
                        setitimer(ITIMER_REAL,&value,NULL);
                 }

void runGame()
{

    while(1)
    {
        
        if(kbhit())
        {
            //snakeMove();
        int ch = getch();
        if(ch==38&&status!=D)
            status=U;
        else if(ch==40&&status!=U)
            status=D;
        else if(ch==39&&status!=R)
            status=L;
        else if(ch==37&&status!=L)
            status=R;
        sleep(10);    
        snakeMove();
        
        }
        
        
    }    
    
}

snakeMove.c

#include"head.h"

void endGame()
{
    exit(0);
}
void cantCrossWall()
{
    if(head->x==10||head->x==WallX+10||head->next==0||head->y==WallY+10)
    {
        //endGamestatus=1;
        endGame();
    }
}
int biteSelf()
{
    snake *self;
    self=head->next;
    while(self!=NULL)
    {
        if(self->x==head->x||self->y==head->y)
            return 1;
        self=self->next;
    }
    return 0;
}
void snakeMove()
{
    cantCrossWall();
//    initSnake();
    snake *nexthead = (snake*)malloc(sizeof(snake));
    switch(status)
    {
        case U: nexthead->x=head->x; nexthead->y=head->y-1;
                   break;
        case D: nexthead->x=head->x ;nexthead->y=head->y+1; 
            break;
        case L: nexthead->x=head->x-1; nexthead->y=head->y;
            break;
        case R: nexthead->x=head->x+1; nexthead->y=head->y;
            break;
    }
    if(nexthead->x==food->x&&nexthead->y==food->y)
    {
        //吃到一口
        nexthead->next=head;
        //表面是把nexthead指针值赋给head,其实是把head的指针域的地址指向原来的nexthead
        head = nexthead;
        //score=score+add;
        initSnake();
        creatFood();
    }
    else                  //没有吃到食物的时候
    {
        if(biteSelf()==1)
        {
            endGame();
        }
        else{
        nexthead->next=head;
        head=nexthead;
        q=head;
        //输出新的蛇头
        printf("\033[%d;%dH\33[47m \033[0m",q->y,q->x);
        //消除蛇的尾巴
        while(q->next->next!=NULL)
        {
            q=q->next;
        }
        printf("\033[%d;%dH\33[40m \033[0m",q->next->y,q->next->x);
        free(q->next);
        q->next=NULL;
                
        }


    }
}

  • 写回答

1条回答 默认 最新

  • sanzhong104204 2021-07-27 13:28
    关注

    kbhit这个和那个while(1)里面都有让输入字符的,是不是少输入了一次?

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 7月28日
  • 创建了问题 7月26日

悬赏问题

  • ¥15 QT任务管理器无法正确获取展开,有悬赏15元速求,如何解决?(相关搜索:标识符|结构体)
  • ¥15 使用delphi 10.3+intraweb 生成的页面怎么实现自动滚屏
  • ¥20 思科:Router c3600 MN-4E插槽
  • ¥15 16进制修改视频的元数据
  • ¥15 HTML中css的位置信息居然会导致元素大小发生变化
  • ¥15 岛津txt格式文件转nirs格式
  • ¥15 石墨烯磁表面等离子体
  • ¥15 angular 项目无法启动
  • ¥15 安装wampserver,图标绿色,但是无法进入软件
  • ¥15 C++ MFC 标准库 加密解密解惑