You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复含2个元素的std::vector使用std::shift_right异常问题

问题分析与修复方案

你的贪吃蛇蛇身显示异常的核心问题在于移动逻辑的顺序错误,以及对std::shift_right的用法理解偏差:

问题1:Movement函数逻辑顺序颠倒

你当前的代码先更新蛇头位置,再调用std::shift_right,这会导致:

  • 当蛇身只有2个元素(头+新添加的身体)时,shift_right会把刚更新的蛇头位置覆盖到身体元素的位置,导致两者重合,视觉上蛇没有增长。
  • 当蛇身有3个元素时,shift_right后前两个元素会变成新蛇头和旧蛇头,第三个元素的位置被覆盖丢失,所以屏幕只显示2个身体部分。

问题2:AddSnakePart的配合问题

虽然push_back(snake_body.back())的逻辑本身没问题,但因为移动逻辑错误,导致新添加的身体部分被立刻覆盖,无法正确显示。


修复后的代码

1. 修正Movement函数

调整逻辑顺序,确保身体部分跟随蛇头的旧位置移动,这里提供两种方案:

方案A:遍历更新身体(推荐,逻辑更直观)

std::vector<SDL_Point> snake_body = { SDL_Point(_PLAYER_START_POS) };

void Player::Movement() 
{
    // 保存当前蛇头的旧位置
    SDL_Point old_head = snake_body.front();

    // 更新蛇头到新位置
    switch (active_valid_input) 
    {
    case SDLK_UP: 
        snake_body.front().y -= _MOVEMENT_UP; // 需根据你的实际步长定义调整
        break;
    case SDLK_DOWN:
        snake_body.front().y += _MOVEMENT_DOWN;
        break;
    case SDLK_RIGHT:
        snake_body.front().x += _MOVEMENT_RIGHT;
        break;
    case SDLK_LEFT:
        snake_body.front().x -= _MOVEMENT_LEFT;
        break;
    default:
        return;
    }

    // 蛇身长度大于1时,从尾到头依次更新身体位置
    if (snake_body.size() > 1) {
        for (size_t i = snake_body.size() - 1; i > 0; --i) {
            SDL_Point temp = snake_body[i];
            snake_body[i] = old_head;
            old_head = temp;
        }
    }
}

方案B:正确使用std::shift_right

如果坚持使用std::shift_right,需调整操作顺序:

void Player::Movement() 
{
    if (snake_body.empty()) return;

    // 先计算新蛇头位置
    SDL_Point new_head = snake_body.front();
    switch (active_valid_input) 
    {
    case SDLK_UP: 
        new_head.y -= _MOVEMENT_UP;
        break;
    case SDLK_DOWN:
        new_head.y += _MOVEMENT_DOWN;
        break;
    case SDLK_RIGHT:
        new_head.x += _MOVEMENT_RIGHT;
        break;
    case SDLK_LEFT:
        new_head.x -= _MOVEMENT_LEFT;
        break;
    default:
        return;
    }

    // 蛇身长度大于1时,移动身体部分
    if (snake_body.size() > 1) {
        // 将身体元素向右移动1位,此时第一个元素值未定义
        std::shift_right(snake_body.begin(), snake_body.end(), 1);
    }

    // 设置新的蛇头位置
    snake_body.front() = new_head;
}

2. AddSnakePart函数(无需修改)

void Player::AddSnakePart() noexcept{
    // 添加当前蛇尾的位置,移动时会自动跟随蛇身轨迹
    snake_body.push_back(snake_body.back());
}

修复原理

  • 遍历更新方式:从蛇尾开始,每个身体段依次移动到前一个段的旧位置,确保蛇身严格跟随蛇头的移动轨迹。
  • std::shift_right正确用法:先把身体段整体右移(让每个段继承前一个段的位置),再设置新蛇头位置,避免蛇头位置被覆盖到身体段。

内容的提问来源于stack exchange,提问作者Walter Medly

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 01:57:38