
本文介绍如何修改骑士移动位置计算方法,使其不依赖固定长度数组或arraylist,而是动态生成仅包含有效位置的精确大小数组。
本文介绍如何修改骑士移动位置计算方法,使其不依赖固定长度数组或arraylist,而是动态生成仅包含有效位置的精确大小数组。
在实现国际象棋中骑士(Knight)的合法移动逻辑时,一个常见误区是预先分配固定长度(如8)的 Position[] 数组,再用 null 填充无效位置——这不仅浪费空间,还迫使调用方额外处理 null 值,降低接口清晰度与安全性。
原方法的问题在于:无论实际有多少个合法移动(0–8个),都返回长度为8的数组,导致结果包含冗余 null 元素。例如,当骑士位于角点 (1,1) 时,仅 (2,3) 和 (3,2) 合法,但方法仍返回 [(2,3), (3,2), null, null, ..., null]。
✅ 正确思路是:两遍遍历法(Two-Pass Approach)
第一遍统计合法移动数量;第二遍填充紧凑数组。无需引入 ArrayList 或其他集合类,完全符合题目约束。
以下是优化后的完整实现:
public Position[] moves(Position p) {
int row = p.getRow();
int col = p.getCol();
// 骑士8个可能的相对位移(行偏移, 列偏移)
int[][] offsets = {{-1,-2},{1,-2},{-1,2},{1,2},{-2,-1},{-2,1},{2,-1},{2,1}};
// 第一遍:统计合法移动数量
int count = 0;
for (int[] offset : offsets) {
int newRow = row + offset[0];
int newCol = col + offset[1];
if (newRow >= 1 && newRow = 1 && newCol = 1 && newRow = 1 && newCol <p>? <strong>关键优势说明:</strong> </p>
- ✅ 零 null 干扰:返回数组不含任何 null,调用方可直接遍历使用;
- ✅ 内存高效:数组长度严格等于合法移动数(如角点返回长度为2的数组);
- ✅ 无额外依赖:不使用 ArrayList、Stream 或第三方库,纯Java标准语法;
- ✅ 边界安全:坐标范围严格校验 1–8(符合题目中基于1的棋盘约定)。
⚠️ 注意事项:
- 确保 Position 类已正确定义且构造函数接受 (row, col) 参数;
- 若未来需支持任意尺寸棋盘(如 n×n),可将 8 替换为参数 boardSize,提升复用性;
- 此方案时间复杂度为 O(1)(因骑士最多8种移动,为常量),空间复杂度也为 O(1)(输出大小上限固定)。
通过该重构,方法语义更精准:moves() 不再是“尝试填充8个槽位”,而是真正“返回所有合法移动位置”——这是健壮API设计的重要一步。










