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

JavaScript中数组的数组存储汉诺塔每步状态异常问题求助

解决汉诺塔步骤状态存储为空的问题

兄弟,我一眼就看出问题出在哪了——你踩了JavaScript引用类型的坑!

你用steps类存储每一步的塔状态时,肯定是直接把塔的数组赋值给了对象属性,比如this.src = src;。但JavaScript里数组是引用类型,所有步骤的src/spr/tgt都会指向同一个数组的内存地址。后续移动圆盘时修改数组,会把之前所有步骤存储的状态一起改掉,最后就只剩初始或最终状态,其他步骤的数组全变成空的。

核心解决方案:给数组做浅拷贝

每次存储状态时,不要直接传原数组,而是创建一个新数组拷贝原数组的内容。因为你的圆盘是简单类型(比如数字),用浅拷贝就足够了,常用的拷贝方式有:

  • 扩展运算符:[...arr]
  • slice()方法:arr.slice()
  • Array.from():Array.from(arr)

修改你的steps类+完整示例

把你的构造函数改成下面这样,确保每个步骤的状态都是独立的:

// 修正后的状态存储类
class Step {
  constructor(src, spr, tgt) {
    // 对每个塔数组做浅拷贝,避免引用共享
    this.src = [...src];
    this.spr = [...spr];
    this.tgt = [...tgt];
  }
}

// 用于存储所有步骤的数组
const allSteps = [];

// 汉诺塔递归函数,同时记录每一步状态
function hanoi(n, src, spr, tgt) {
  if (n === 1) {
    // 移动单个圆盘
    const disk = src.pop();
    tgt.push(disk);
    // 存储当前状态,注意这里也要拷贝当前的三个塔数组
    allSteps.push(new Step([...src], [...spr], [...tgt]));
    return;
  }
  
  hanoi(n - 1, src, tgt, spr);
  
  // 移动第n个圆盘
  const disk = src.pop();
  tgt.push(disk);
  // 存储移动后的状态
  allSteps.push(new Step([...src], [...spr], [...tgt]));
  
  hanoi(n - 1, spr, src, tgt);
}

// 初始化三个塔:src塔有8个圆盘,其余为空
const srcTower = [8,7,6,5,4,3,2,1];
const sprTower = [];
const tgtTower = [];

// 先存储初始状态(这一步别忘!)
allSteps.push(new Step([...srcTower], [...sprTower], [...tgtTower]));

// 执行汉诺塔算法
hanoi(8, srcTower, sprTower, tgtTower);

// 现在检查结果:应该有256个状态(初始+255步)
console.log(allSteps.length); // 输出256
console.log(allSteps[0].src); // 初始状态:[8,7,6,5,4,3,2,1]
console.log(allSteps[255].tgt); // 最终状态:[8,7,6,5,4,3,2,1]

关键注意点

  • 初始状态要单独存储:因为递归函数里存储的是移动后的状态,初始的满盘状态需要手动添加到数组里。
  • 每次移动后都要存储:递归的每一步移动完成后,都要创建新的Step实例存储当前状态,确保每一步都被记录。
  • 拷贝时机要对:无论是构造函数里还是存储状态时,都要对当前的塔数组做拷贝,不能直接传原数组引用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:23:53