贪吃蛇容易踩的坑

相信很多学习编程的小伙伴们都写/抄过“贪吃蛇”这个小游戏吧
我们先引入一段代码

#python
while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            terminate()
        elif event.type == KEYDOWN:
            if (event.key == K_LEFT or event.key == K_a) and direction != RIGHT:
                direction = LEFT
            elif (event.key == K_RIGHT or event.key == K_d) and direction != LEFT:
                direction = RIGHT
            elif (event.key == K_UP or event.key == K_w) and direction != DOWN:
                direction = UP
            elif (event.key == K_DOWN or event.key == K_s) and direction != UP:
                direction = DOWN
            elif event.key == K_ESCAPE:
                terminate()
// c\c++
void dir_control(char _dir){
    switch(_dir)
    {
    case 's': this->dir = go_stop;
        break;
    case 'l': if(this->dir != go_right)this->dir = go_left;
        break;
    case 'r': if(this->dir != go_left)this->dir = go_right;
        break;
    case 'u': if(this->dir != go_down)this->dir = go_up;
        break;
    case 'd': if(this->dir != go_up)this->dir = go_down;
        break;
    }
}

怎么样,写过的朋友们看上去是不是感觉非常的眼熟,没写过的也没关系,听我解释一下。

  • 贪吃蛇实现的一般思路:
    • 初始化,将地图造出来。
    • 如果有键盘输入的话,就重新设置运动方向。
    • 制造食物。
    • 让蛇移动,如果吃掉食物就重新生成一个食物,如果会死亡就break。
    • 用蛇的坐标将地图中的空格替换为’#‘和’@’,将食物所在的坐标设置为’O’。
    • 输出视图,即将最终生成的地图打印出来。
    • Sleep(n) 暂停n毫秒之后在进行上面的。

上述的代码是在刷新贪吃蛇游戏界面(刷新画布)前,先去检测一下是否有用户输入,有输入就把输入取出,然后根据情况去改变贪吃蛇的移动方向(本质是改变蛇头的移动方向)。

到这里为止,是不是感觉没什么问题,确实,大家也都是这么做、这么写的。(然后我就是在这里,遇到了那个bug)
在玩的过程中,有的时候我们想让蛇快速的完成两次转向,一些速度快的贪吃蛇能够正确做出反应,不过有一些慢的,你就会发现你莫名奇妙的就 game over 了(我不知道你们有没有遇到过,反正我能找到的贪吃蛇代码、贪吃蛇开发教程等,下载下来试玩,都会遇到这个问题;相信能看到这篇文章的你一定也遇到了)

为什么会有这样的问题?

再回过去看代码,或者去看看网上能找到代码,都是在检测到方向键后直接去改变蛇的运动方向,然后根据方向变量的值move snake,然后因为要控制蛇的移动速度,会加上一小段的延迟。
那么问题来了,当我操作得很快,在延迟还没结束的时候,先后按下了正确的两个方向变更按键。
那是不是在下一次刷新画面前,检测按键会检测到两次按下并变更、或者是只检测到后面那次变更?
对,这两者都会产生问题:前者会连续2次改变蛇运动方向变量,使蛇头之后开始反向运动,导致吃到身体,game over;后者因为只检测到后一次的输入,而后一次输入是在上次输入被检测并正确执行的预期之上的,这就相当于检测到的输入与原来的运动方向相反或者同向,不发生变化,在你看来就好像自己啥都没按一样。

如何解决

我的解决方法是,将输入存入队列,每次move snake前从队列头部取出一个值,进行对应的按键操作。(将按键检测作为协程)
还有嘛,就是不要方向变量,按键按下时直接操作整条蛇的移动。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值