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
相关产品推荐
相关产品推荐

