修复基于多维向量实现的玩家移动地图的vector下标越界崩溃问题
解决地图移动系统中vector下标越界的崩溃问题
首先,咱们来拆解一下你代码里导致崩溃的核心问题,然后一步步修复:
问题根源分析
- 越界触发在判断之前:你的
Player_Pos函数开头先执行了this->map[posY][posX] = '#',当moveY已经到10时(你的地图是10行,下标范围是0-9),这行代码会直接访问不存在的下标,程序在进入后面的边界判断前就已经崩溃了。 - 循环遍历逻辑错误:
Update函数的内层循环用了map.size()来遍历列,这应该改成map[i].size(),否则如果地图的行和列数不同,会导致列遍历出错。 - 不必要的浮点类型:
moveY和moveX用float完全没必要,数组下标是整数,浮点类型可能带来精度问题,而且访问数组时的隐式转换容易埋下隐患。 - 硬编码边界不灵活:直接判断
moveY == 10太死板,如果以后修改地图尺寸,这段判断就失效了,应该基于地图的实际尺寸做判断。
修复后的完整代码
#include <iostream> #include <vector> #include <Windows.h> class Map { private: int moveY = 0; // 改为int类型,适配数组下标 int moveX = 0; std::vector<std::vector<char>> map; public: Map(int dim1, int dim2, char type) { map.resize(dim1, std::vector<char>(dim2, type)); } bool Update() { system("cls"); for (int i = 0; i < map.size(); i++) { for (int j = 0; j < map[i].size(); j++) { // 修正:用map[i].size()获取当前行的列数 std::cout << map[i][j]; } std::cout << '\n'; } return true; } bool Player_Pos(int posY, int posX); // 参数同步改为int int posY() { return moveY; } int posX() { return moveX; } }; bool Map::Player_Pos(int posY, int posX) { // 先处理按键输入与边界判断,再修改地图,避免提前访问越界下标 if (GetAsyncKeyState(0x28) & 0x8000) { // 加上&0x8000确保判断按键按下的状态 // 向下移动边界:不能超过最后一行的下标(map.size()-1) if (moveY >= map.size() - 1) { this->map[posY][posX] = '#'; // 保持当前玩家位置标记 return false; } this->map[posY][posX] = '.'; // 清除原位置 moveY += 1; } // 补充上方向的边界判断 if (GetAsyncKeyState(0x26) & 0x8000) { if (moveY <= 0) { this->map[posY][posX] = '#'; return false; } this->map[posY][posX] = '.'; moveY -= 1; } // 补充左方向的边界判断 if (GetAsyncKeyState(0x25) & 0x8000) { if (moveX <= 0) { this->map[posY][posX] = '#'; return false; } this->map[posY][posX] = '.'; moveX -= 1; } // 补充右方向的边界判断 if (GetAsyncKeyState(0x27) & 0x8000) { if (moveX >= map[0].size() - 1) { // 假设所有行的列数一致 this->map[posY][posX] = '#'; return false; } this->map[posY][posX] = '.'; moveX += 1; } // 设置新的玩家位置 this->map[moveY][moveX] = '#'; return true; } int main() { Map map = Map(10, 10, '.'); while (true) { map.Player_Pos(map.posY(), map.posX()); map.Update(); Sleep(100); // 增加延时,减少屏幕闪烁 } return 0; }
关键修改点说明
- 变量类型优化:把
moveY和moveX改为int,彻底避免浮点类型带来的精度问题,也更贴合数组下标的使用场景。 - 执行顺序调整:先处理按键和边界判断,确认可以移动后再修改地图,最后设置新的玩家位置,从根源上避免了越界访问。
- 按键判断修正:
GetAsyncKeyState的返回值需要和0x8000做位与运算,才能准确判断按键是否处于按下状态,避免误触发。 - 灵活边界判断:用
map.size()-1和map[0].size()-1代替硬编码的数值,让代码适配不同尺寸的地图。 - 补充全方向处理:不仅修复了向下移动的问题,还完善了上、左、右三个方向的移动和边界判断,让整个移动逻辑更完整。
- 添加延时:主循环中加入
Sleep(100),降低刷新频率,解决屏幕闪烁的问题,提升操作体验。
内容的提问来源于stack exchange,提问作者NewbCoder
相关产品推荐
相关产品推荐

