如何修复含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
相关产品推荐
相关产品推荐

