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

修复基于多维向量实现的玩家移动地图的vector下标越界崩溃问题

解决地图移动系统中vector下标越界的崩溃问题

首先,咱们来拆解一下你代码里导致崩溃的核心问题,然后一步步修复:

问题根源分析

  1. 越界触发在判断之前:你的Player_Pos函数开头先执行了this->map[posY][posX] = '#',当moveY已经到10时(你的地图是10行,下标范围是0-9),这行代码会直接访问不存在的下标,程序在进入后面的边界判断前就已经崩溃了。
  2. 循环遍历逻辑错误:Update函数的内层循环用了map.size()来遍历列,这应该改成map[i].size(),否则如果地图的行和列数不同,会导致列遍历出错。
  3. 不必要的浮点类型:moveY和moveX用float完全没必要,数组下标是整数,浮点类型可能带来精度问题,而且访问数组时的隐式转换容易埋下隐患。
  4. 硬编码边界不灵活:直接判断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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 22:22:44