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

如何避免访问二维数组中的无效位置?(骑士巡游问题场景)

骑士巡游边界校验优化方案

方案1:预定义偏移量统一校验

骑士的8种移动偏移是固定值,我们可以先把所有偏移量存为常量数组,遍历所有偏移后统一做边界校验,无需编写多组独立的if判断,代码更简洁易维护:

// 预定义骑士8种移动的行、列偏移量
int[][] knightOffsets = {{-2, -1}, {-2, 1}, {-1, -2}, {-1, 2}, {1, -2}, {1, 2}, {2, -1}, {2, 1}};
ArrayList<int[]> validMoves = new ArrayList<>();
int boardSize = 8;

for (int[] offset : knightOffsets) {
    int newRow = currentRow + offset[0];
    int newCol = currentColumn + offset[1];
    // 同时校验边界+是否未访问
    if (newRow >= 0 && newRow < boardSize && newCol >= 0 && newCol < boardSize && table[newRow][newCol] == 0) {
        validMoves.add(new int[]{newRow, newCol});
    }
}

// 后续直接遍历validMoves做递归即可

注意:你原有代码中反复复用同一个arr数组对象,ArrayList存储的是对象引用,会导致所有添加的元素都和最后一次赋值的arr值一致,上述方案中每次添加都创建新数组解决了这个bug。

方案2:扩展棋盘边缘,完全省略边界判断

如果想要你理想中无需判断边界、直接访问的效果,可以把棋盘数组向外扩展骑士最大移动步长(2格)的宽度,边缘区域预先标记为不可用(非0值),访问越界位置时实际访问的是边缘的不可用区域,不会触发数组越界,自动被过滤:

// 初始化12x12的扩展棋盘,边缘2层赋值为-1(不可用),中间8x8为实际棋盘,初始值0
int[][] table = new int[12][12];
for (int i = 0; i < 12; i++) {
    for (int j = 0; j < 12; j++) {
        table[i][j] = (i < 2 || i >= 10 || j < 2 || j >= 10) ? -1 : 0;
    }
}

// 后续获取合法移动时无需判断边界
int[][] knightOffsets = {{-2, -1}, {-2, 1}, {-1, -2}, {-1, 2}, {1, -2}, {1, 2}, {2, -1}, {2, 1}};
ArrayList<int[]> validMoves = new ArrayList<>();
// 注意:实际使用的棋盘坐标要统一加2,比如初始位置(0,0)对应扩展棋盘的(2,2)
for (int[] offset : knightOffsets) {
    int newRow = currentRow + offset[0];
    int newCol = currentColumn + offset[1];
    if (table[newRow][newCol] == 0) {
        validMoves.add(new int[]{newRow, newCol});
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 17:36:02