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

JS汉诺塔实现问题:移动时双塔同步更新及无效移动异常

汉诺塔JS实现的两个典型bug修复方案

嘿,我刚看到你在练习JS构造函数和原型时遇到的汉诺塔问题,这两个bug其实挺典型的,我帮你拆解分析并给出解决方案~

问题1:移动tower[0]到tower[1]时,tower[2]同步添加圆盘

这个问题几乎可以肯定是数组引用复用导致的。如果你初始化三个塔时,不小心让它们指向了同一个数组对象,那修改任意一个塔都会同步影响另外两个——因为它们本质上是同一个数组的不同引用。

错误示例(导致引用复用)

function HanoiTower(n) {
  const initialDiscs = Array.from({length: n}, (_, i) => n - i);
  // 踩坑:三个塔共用同一个数组引用!
  this.towers = [initialDiscs, initialDiscs, initialDiscs];
}

修复方案:给每个塔创建独立数组

通过slice()复制初始圆盘数组,或者分别初始化空数组,确保三个塔是完全独立的对象:

function HanoiTower(n) {
  const initialDiscs = Array.from({length: n}, (_, i) => n - i);
  // 每个塔都是独立的数组实例
  this.towers = [initialDiscs.slice(), [], []];
}

问题2:无效移动时原塔的圆盘仍被移走

这个问题是因为你在执行移动前没有做合法性校验,直接执行了pop()操作。汉诺塔的合法移动需要满足两个条件:

  1. 源塔不为空
  2. 要移动的圆盘比目标塔的顶部圆盘小(或目标塔为空)

错误示例(无校验直接移动)

HanoiTower.prototype.move = function(from, to) {
  // 不管合法与否,直接弹出源塔圆盘
  const disc = this.towers[from].pop();
  this.towers[to].push(disc);
}

修复方案:先校验再执行移动

在移动前先判断合法性,只有符合规则才执行pop()和push():

HanoiTower.prototype.move = function(from, to) {
  const sourceTower = this.towers[from];
  const targetTower = this.towers[to];

  // 校验1:源塔不能为空
  if (sourceTower.length === 0) {
    console.log('❌ 源塔为空,无法移动!');
    return;
  }

  const movingDisc = sourceTower[sourceTower.length - 1];
  const targetTopDisc = targetTower[targetTower.length - 1];

  // 校验2:目标塔为空,或移动圆盘小于目标顶部圆盘
  if (targetTower.length === 0 || movingDisc < targetTopDisc) {
    // 合法移动:执行弹出和添加
    targetTower.push(sourceTower.pop());
    console.log(`✅ 成功将圆盘${movingDisc}从塔${from}移到塔${to}`);
  } else {
    console.log(`❌ 无效移动:圆盘${movingDisc}不能放在圆盘${targetTopDisc}上!`);
  }
}

完整可运行示例

把上面的修正整合起来,你可以测试这个完整的实现:

function HanoiTower(n) {
  const initialDiscs = Array.from({length: n}, (_, i) => n - i);
  this.towers = [initialDiscs.slice(), [], []];
}

HanoiTower.prototype.move = function(from, to) {
  const sourceTower = this.towers[from];
  const targetTower = this.towers[to];

  if (sourceTower.length === 0) {
    console.log('❌ 源塔为空,无法移动!');
    return;
  }

  const movingDisc = sourceTower.at(-1);
  const targetTopDisc = targetTower.at(-1);

  if (targetTower.length === 0 || movingDisc < targetTopDisc) {
    targetTower.push(sourceTower.pop());
    console.log(`✅ 移动成功:塔${from} → 塔${to}`);
    console.log('当前塔状态:', this.towers);
  } else {
    console.log(`❌ 无效移动:圆盘${movingDisc}不能放在${targetTopDisc}上!`);
  }
}

// 测试用例
const tower = new HanoiTower(3);
tower.move(0, 1); // 合法移动
tower.move(0, 1); // 尝试把大圆盘放小圆盘上,会提示无效
tower.move(0, 2); // 合法移动

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:26:54