如何重置汉诺塔游戏及优化JavaScript实现方案咨询
汉诺塔游戏重置方法与代码优化建议
一、重置游戏到初始状态的方法
要实现重置,首先得保存初始状态的独立副本(避免引用关联导致初始值被意外修改),然后编写单独的重置函数恢复盘面:
- 先定义初始柱子模板:
const initialTower = [5, 4, 3, 2, 1]; - 重置时用展开运算符
[...initialTower]创建新数组,确保和原模板无引用关联 - 重置函数示例:
function resetGame() { board = [ [...initialTower], // 第一个柱子恢复初始状态 [], // 第二个柱子清空 [] // 第三个柱子清空 ]; console.table(board); }
二、代码优化细节
1. 拆分内部函数,避免重复创建
原arrMove内部的winAndReset、arrayEquals每次调用都会重新定义,将它们移到全局作用域,提升性能且结构更清晰:
// 全局复用的工具函数 function arrayEquals(a, b) { return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((val, index) => val === b[index]); } function winAndReset() { alert("You have won"); resetGame(); // 获胜后自动触发重置 }
2. 简化盘面拷贝逻辑
原来的嵌套map可以用展开运算符简化,代码更易读:
// 替代双层map的拷贝方式 const newBoard = board.map(tower => [...tower]);
3. 修正移动合法性判断逻辑
原代码在目标柱为空时,会取到undefined导致比较逻辑异常。优化后仅在目标柱有元素时判断大小:
const fromTower = newBoard[oldIndex]; const toTower = newBoard[newIndex]; const movingDisk = fromTower[fromTower.length - 1]; // 合法性校验:源柱不能为空,且目标柱为空/目标柱顶部圆盘更大 if (!movingDisk) { alert("Illegal Move: 源柱没有圆盘可移动"); } else if (toTower.length > 0 && movingDisk > toTower[toTower.length - 1]) { alert("Illegal Move: 不能把大圆盘放在小圆盘上"); } else { toTower.push(fromTower.pop()); }
4. 简化函数调用与命名
- 将
arrMove改名为makeMove,语义更明确 - 由于
board是全局变量,无需每次传参,调用时仅需传入源柱和目标柱索引(比如makeMove(0, 2)表示从第一个柱子移到第三个)
5. 合并获胜判断逻辑
把两个获胜条件合并,代码更简洁:
if (arrayEquals(newBoard[1], initialTower) || arrayEquals(newBoard[2], initialTower)) { winAndReset(); }
三、优化后的完整代码
// 初始盘面模板(保存独立副本) const initialTower = [5, 4, 3, 2, 1]; // 初始化游戏盘面 let board = [ [...initialTower], [], [] ]; // 重置游戏函数 function resetGame() { board = [ [...initialTower], [], [] ]; console.table(board); } // 判断两个数组是否相等的工具函数 function arrayEquals(a, b) { return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((val, index) => val === b[index]); } // 获胜提示并重置 function winAndReset() { alert("You have won"); resetGame(); } // 执行移动操作的核心函数 function makeMove(fromIndex, toIndex) { // 创建盘面副本,避免直接修改原数组 const newBoard = board.map(tower => [...tower]); const fromTower = newBoard[fromIndex]; const toTower = newBoard[toIndex]; const movingDisk = fromTower[fromTower.length - 1]; // 合法性校验不通过则终止函数 if (!movingDisk) { alert("Illegal Move: 源柱没有圆盘可移动"); return; } if (toTower.length > 0 && movingDisk > toTower[toTower.length - 1]) { alert("Illegal Move: 不能把大圆盘放在小圆盘上"); return; } // 执行合法移动 toTower.push(fromTower.pop()); // 检查是否获胜 if (arrayEquals(newBoard[1], initialTower) || arrayEquals(newBoard[2], initialTower)) { winAndReset(); } // 更新全局盘面 board = newBoard; console.table(board); }
使用说明
- 重置游戏:直接调用
resetGame() - 执行移动:比如从第一个柱子移到第三个,调用
makeMove(0, 2)(柱子索引从0开始)
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

