有关贪吃蛇移动问题

贪吃蛇游戏是一款耳熟能详的小游戏,通过上下左右控制蛇的方向,寻找吃的果子,每吃一口果子,蛇的身子会越吃越长,身子越长玩的难度就越大,不能碰墙,不能咬到自己的身体,更不能咬自己的尾巴,吃完所有果子,就能过关,然后继续玩下一关。

该游戏的核心是通过链表中的节点位置(假设节点中的x,y来表示节点所在的位置信息)和节点个数来描述蛇的长度和身体位置信息,移动方向即控制链表节点的位置信息。假设节点之间采用双向链表的形式进行连接。根据上述描述:

看此题,也就是说,整个贪吃蛇其实是一个链表,但是这个链表的节点在我们的观测中其实是它的x值和y值。x,y代表蛇每个节点的位置,然后靠指针连接起来。头是头,我们假设是个无头链表

(1) 请简要回答在不考虑吃到果子的前提下,贪吃蛇每上下左右移动一格,设计时如何对链表操作能达到高效的移动?

在不吃果子的前提下,也就是长度没有改变,没有添加新的节点,只有x,y的改变,向上移动也就是头节点的y+1;其余的节点的x,y值变成它前一个节点的值,在程序中需要从尾巴处遍历到头,再改变头的值为了防止原本头节点的值丢失。

或者直接改变尾巴的值,让尾巴的值改变为需要移动到的地点的值,将尾巴与身体断开,再将它连接到头上,成为新的头。

(2) 请实现贪吃蛇移动的函数,考虑移动时分别当吃到果子和没有吃的果子的场景,同时还要判断在移动一步之后是否会造成碰到蛇自己本身(不考虑碰壁),即当蛇的头部碰到蛇身体任何部分即表示失败。

int SnakeMove(Food_S *pFood, SLIST_S *pHeadSnake, SLIST_S *pTailSnake);

函数说明:

参数pFood:作为入参表示蛇下一个移动的位置,当成员IsHaveFood为FLASE时表示仅仅只是移动位置,当IsHaveFood为TRUE时,表示吃到了果子;

参数pHeadSnake、pTailSnake:分别表示贪吃蛇的头尾节点,即是入参也是出参;

返回值:表示贪吃蛇移动函数的结果是成功还是失败,0表示成功, -1表示失败;

typedef struct SLIST{

int x;

int y;

struct SLIST *prev;

struct SLIST *next;

}SLIST_S;

typedef struct Food{

int x;

int y;

bool IsHaveFood;

}Food_S;

int SnakeMove(Food_S *pFood, SLIST_S *pHeadSnake, SLIST_S *pTailSnake);

题目已经给了三要素,要写的东西大致已经定下来了。

第一个参数是要移动的位置(包括是否有果子的判断)

第二个参数是头指针

第三个参数是尾指针

入参也就是出参,因为返回值已经确定,所以,我们只能用参数来传递头指针和尾指针的值,对于指针来说是值传递,如果指针本身的值在函数内发生改变,是不会影响外面的头指针和尾指针的值的(传递不出来),能改变的只有头指针和尾指针指向的位置的内容,这个可以传递出来。

我们需要写的是两个个判断,是否撞到自己,是否吃到果子,因为撞到自己的画面出来后才会结束,所以我们先写移动

//贪吃蛇移动
int SnakeMove(Food_S *pFood,  SLIST_S *pHeadSnake,  SLIST_S *pTailSnake)
{
    //判断是否吃到果子 没吃到
    if(pFood->IsHaveFood==FLASE)
    {//遍历从尾巴开始赋移动后的值(后一个节点移动后的值为前一个节点的值)
       while(pTailSnake->prev==NULL)
       {
        pTailSnake->x= pTailSnake->prev->x;
        pTailSnake->y= pTailSnake->prev->y;
        pTailSnake=pTailSnake->prev;  
       }
       pheadSnake->x=pFood->x;
       pHeadSnake->y=pFood->y;
    }
    //判断是否吃到桃子 吃到
    if(pFood->IsHaveFood==TRUE)
    {
      //需要增加节点
      SLIST_S *pNew=(SLIST_S *)malloc(sizeof(SLIST_S));
      //新加的节点替代原本的头结点
      pNew->x=pHeadSnake->x;
      pNew->y=pHeadSnake->y;
      pNew->next=pHeadSnake->next;
      pnew->prev=pHeadSnake;
      //旧头结点成为新头节点
      pHeadSnake->x=pFood->x;
      pHeadSnake->y=pFood->y;
      pHeadSnake->next=pNew;
      pHeadSnake->perv=NULL;
    }
    //判断是否撞到自己
    while(pHeadSnake->next!=NULL)
    {
     if(pFood->x==pHeadSnake->next->x&&pFood->y==pHeadSnake->next->y)
     {
      return -1;
     }
     pHeadSnake=pHeadSnake->next;
    }    
 return 0;
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值