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()操作。汉诺塔的合法移动需要满足两个条件:
- 源塔不为空
- 要移动的圆盘比目标塔的顶部圆盘小(或目标塔为空)
错误示例(无校验直接移动)
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
相关产品推荐
相关产品推荐

