HarmonyOS 小游戏《对战五子棋》开发第9篇 - GomokuEngine核心引擎设计(四):悔棋功能与历史记录管理

📅 2026/7/7 1:26:25
HarmonyOS 小游戏《对战五子棋》开发第9篇 - GomokuEngine核心引擎设计(四):悔棋功能与历史记录管理
悔棋是棋类游戏的标配——history数组的力量截图如下undo方法完整解析undo():boolean{// 1. 检查是否有棋可悔if(this.history.length0){returnfalse;}// 2. 弹出最后一步constlastMovethis.history.pop()!;this.board[lastMove.row][lastMove.col]EMPTY;// 3. 切换回上一个玩家this.currentPlayerthis.currentPlayerBLACK?WHITE:BLACK;// 4. 重置游戏状态this.resultGameResult.PLAYING;// 5. 更新lastMoveif(this.history.length0){constprevthis.history[this.history.length-1];this.lastMovenewMove(prev.row,prev.col);}else{this.lastMovenull;}returntrue;}悔棋的核心步骤步骤1空历史检查if(this.history.length0)returnfalse;没有落子记录时不能悔棋。步骤2撤销棋子constlastMovethis.history.pop()!;this.board[lastMove.row][lastMove.col]EMPTY;pop()移除并返回数组最后一个元素。!是非空断言——因为我们已经检查了length 0。步骤3切换玩家this.currentPlayerthis.currentPlayerBLACK?WHITE:BLACK;悔棋后当前玩家变回之前落子的玩家——因为那步棋被撤销了。步骤4重置游戏结果this.resultGameResult.PLAYING;即使之前已经分出胜负悔棋后游戏重新进入PLAYING状态。这是一个重要的设计决策——允许在游戏结束后悔棋继续游戏。步骤5更新lastMoveif(this.history.length0){constprevthis.history[this.history.length-1];this.lastMovenewMove(prev.row,prev.col);}else{this.lastMovenull;}如果还有历史记录lastMove指向倒数第二个落子否则置为null。history数组的多重作用悔棋功能history.pop()撤销最后一步空棋盘判断history.length 0等价于棋盘为空手数统计history.length就是当前手数复盘功能未来扩展可以回放整个对局UI层的悔棋控制// TwoPlayerPage中Button(悔棋).enabled(this.moveCount0this.resultGameResult.PLAYING).onClick((){this.undo();})privateundo():void{this.engine.undo();this.refreshBoardData();}UI层通过enabled控制悔棋按钮的可点击状态——只有手数0且游戏进行中才允许悔棋。AI对战中的悔棋问题本项目在AI对战模式中没有提供悔棋功能。如果需要实现需要撤销两步玩家AI// 假设的AI悔棋逻辑privateundoInAIBattle():void{this.engine.undo();// 撤销AI的落子this.engine.undo();// 撤销玩家的落子this.refreshBoardData();}对比其他撤销方案方案1history数组本项目优点简单直观O(1)撤销缺点需要额外的内存存储历史方案2保存棋盘快照// 每次落子前保存棋盘副本constsnapshotthis.board.map(row[...row]);snapshots.push(snapshot);// 悔棋时恢复this.boardsnapshots.pop();优点可以撤销到任意状态缺点内存开销大每次保存整个棋盘方案3命令模式classPlaceCommand{execute(board){/* 落子 */}undo(board){/* 撤销 */}}优点扩展性强支持复杂操作缺点过度设计本项目选择了最简单有效的方案1。总结悔棋功能的实现展示了history数组的多重价值——它不仅是悔棋的基础还是手数统计和空棋盘判断的依据。一个好的数据结构设计可以让多个功能自然涌现。