
好的架构让代码像积木一样可拼装、可替换为什么需要架构设计五子棋看似简单但如果把所有逻辑写在一个文件里很快就会变成一团乱麻。本项目采用了类MVC的三层架构┌─────────────────────────────────┐ │ View 层 (UI) │ │ Index / TwoPlayerPage / │ │ AIBattlePage / ChessBoardView │ └──────────┬──────────────────────┘ │ 调用引擎方法 / 接收回调 ┌──────────▼──────────────────────┐ │ Controller/Engine 层 │ │ GomokuEngine (核心引擎) │ │ AIPlayer (AI控制器) │ └──────────┬──────────────────────┘ │ 操作 ┌──────────▼──────────────────────┐ │ Model 层 (数据) │ │ board[][] / history[] / result │ │ GameConstants (常量与类型) │ └─────────────────────────────────┘Model层GameConstants// GameConstants.ets — 纯数据定义无任何逻辑exportconstBOARD_SIZE:number15;exportconstEMPTY:number0;exportconstBLACK:number1;exportconstWHITE:number2;exportenumDifficulty{EASY1,NORMAL2,HARD3}exportenumGameResult{PLAYING0,BLACK_WIN1,WHITE_WIN2,DRAW3}exportclassMove{row:number;col:number;constructor(row:number,col:number){this.rowrow;this.colcol;}}Model层只定义是什么不关心怎么做。这些常量和类型被所有层共享。Engine层GomokuEngine引擎层是纯逻辑不依赖任何UI框架exportclassGomokuEngine{board:number[][];currentPlayer:number;result:GameResult;history:Move[];lastMove:Move|null;placePiece(row:number,col:number,player:number):boolean{/* ... */}checkWin(row:number,col:number,player:number):boolean{/* ... */}undo():boolean{/* ... */}reset():void{/* ... */}toFlatArray():number[]{/* ... */}}关键设计决策引擎不import任何ArkUI模块——可以在Node.js中测试引擎不主动通知UI——由调用方负责刷新引擎返回基本类型boolean/number[]——UI层自行解读View层页面与组件View层负责渲染引擎状态并将用户输入传递给引擎EntryComponentstruct TwoPlayerPage{privateengine:GomokuEnginenewGomokuEngine();// 持有引擎实例StateboardData:number[][];// 从引擎同步的状态StatecurrentPlayer:numberBLACK;Stateresult:GameResultGameResult.PLAYING;// View → Engine用户点击落子privateonCellClick(row:number,col:number):void{constsuccessthis.engine.placePiece(row,col,this.currentPlayer);if(success){this.refreshBoardData();// Engine → View同步状态}}// 从引擎同步数据到UI状态privaterefreshBoardData():void{this.boardDatathis.engine.toFlatArray();this.currentPlayerthis.engine.currentPlayer;this.resultthis.engine.result;}}数据流向用户点击棋盘 ↓ ChessBoardView.handleClick() → onCellClick回调 ↓ TwoPlayerPage.onCellClick() → engine.placePiece() ↓ GomokuEngine修改board[][]更新result ↓ refreshBoardData() 同步到 State ↓ State变化触发UI重绘 ↓ ChessBoardView的Watch(onDataChange)触发drawBoard()可复用组件设计ChessBoardView是纯粹的表现组件Componentexportstruct ChessBoardView{PropWatch(onDataChange)boardData:number[][];// 输入ProplastMoveRow:number-1;// 输入ProplastMoveCol:number-1;// 输入onCellClick:(row:number,col:number)void(){};// 输出回调}它不关心数据从哪来双人对战还是AI对战只负责根据boardData绘制棋盘将点击事件通过回调传出这种设计使得ChessBoardView被两个页面复用而无需任何修改。AIPlayer的架构角色AIPlayer本质上是一个虚拟控制器——它读取引擎状态计算出最佳落子然后由页面层调用引擎落子// AIBattlePage中constmovethis.aiPlayer.getMove(this.engine.board);// AI计算this.engine.placePiece(move.row,move.col,WHITE);// 引擎执行AIPlayer不直接修改棋盘保持了引擎对棋盘的独占控制权。架构优势可测试性GomokuEngine和AIPlayer可以脱离UI单独测试可复用性ChessBoardView被两个页面复用可扩展性添加新AI算法只需继承或替换AIPlayer可维护性修改UI不影响游戏逻辑反之亦然总结好的架构不是过度设计而是恰到好处的分层。本项目通过Model-Engine-View三层分离实现了逻辑与表现的解耦。引擎层是项目的核心UI层是引擎的显示器AI层是引擎的智能大脑。附