好的常量设计让代码自文档化——从GameConstants看类型定义的艺术
代码如下:
/** * GameConstants.ets - 五子棋游戏常量与类型定义 *//** 棋盘尺寸 15x15 */exportconstBOARD_SIZE:number=15;/** 空位 */exportconstEMPTY:number=0;/** 黑棋 */exportconstBLACK:number=1;/** 白棋 */exportconstWHITE:number=2;/** AI难度等级 */exportenumDifficulty{EASY=1,NORMAL=2,HARD=3}/** 游戏结果 */exportenumGameResult{PLAYING=0,BLACK_WIN=1,WHITE_WIN=2,DRAW=3}/** 落子位置 */exportclassMove{row:number;col:number;constructor(row:number,col:number){this.row=row;this.col=col;}}/** 获取对手棋色 */exportfunctiongetOpponent(player:number):number{returnplayer===BLACK?WHITE:BLACK;}/** 颜色名称 */exportfunctionplayerName(player:number):string{returnplayer===BLACK?'黑方':'白方';}为什么需要独立的常量文件
在游戏开发中,"魔法数字"是代码质量的头号杀手。对比两种写法:
// 差:到处是魔法数字if(board[7][7]===0){...}if(count>=5)returntrue;this.currentPlayer=player===1?2:1;// 好:语义清晰if(board[7][7]===EMPTY){...}if(count>=5)returntrue;// 5是五子棋的固有规则,可以接受this.currentPlayer=player===BLACK?WHITE:BLACK;GameConstants完整解析
exportconstBOARD_SIZE:number=15;// 15x15标准棋盘exportconstEMPTY:number=0;// 空位exportconstBLACK:number=1;// 黑棋exportconstWHITE:number=2;// 白棋为什么棋子用数字而不是字符串
- 性能:数字比较比字符串快
- 内存:number占用的内存远小于string
- 数组存储:棋盘是
number[][],用数字最自然 - 序列化:数字序列化/反序列化更简单
枚举设计
exportenumDifficulty{EASY=1,NORMAL=2,HARD=3}exportenumGameResult{PLAYING=0,BLACK_WIN=1,WHITE_WIN=2,DRAW=3}设计要点:
- 枚举值从1开始(0留给"无"或默认状态)
GameResult.PLAYING = 0作为默认值- 枚举名用大写驼峰,语义明确
Move类
exportclassMove{row:number;col:number;constructor(row:number,col:number){this.row=row;this.col=col;}}Move是五子棋中最基础的数据结构——表示棋盘上的一个位置。用class而非interface是因为Move经常需要new Move(row, col)创建实例。
辅助函数
exportfunctiongetOpponent(player:number):number{returnplayer===BLACK?WHITE:BLACK;}exportfunctionplayerName(player:number):string{returnplayer===BLACK?'黑方':'白方';}这两个工具函数被多处复用:
getOpponent:引擎中切换玩家、AI中获取人类棋色playerName:UI中显示当前玩家
常量设计的通用原则
1. 集中管理
所有游戏常量放在一个文件中,方便查找和修改:
// 改棋盘大小只需改一处exportconstBOARD_SIZE:number=15;// 改成19就是围棋棋盘2. 命名清晰
BOARD_SIZE而非SIZE或BSEMPTY而非EMPTY_CELL或NONEBLACK/WHITE而非COLOR_BLACK/COLOR_WHITE
3. 语义分组
// 棋盘相关exportconstBOARD_SIZE=15;exportconstEMPTY=0;// 棋子相关exportconstBLACK=1;exportconstWHITE=2;// 游戏状态exportenumGameResult{...}// AI相关exportenumDifficulty{...}AI评分常量
AIPlayer中定义了一套完整的评分常量:
constSCORE_FIVE:number=1000000;// 五连constSCORE_OPEN_FOUR:number=100000;// 活四constSCORE_FOUR:number=10000;// 冲四constSCORE_OPEN_THREE:number=8000;// 活三constSCORE_THREE:number=500;// 眠三constSCORE_OPEN_TWO:number=400;// 活二constSCORE_TWO:number=50;// 眠二constSCORE_ONE:number=10;// 单子分值设计逻辑:
- 五连 > 活四 > 冲四 > 活三 > 眠三 > 活二 > 眠二 > 单子
- 相邻级别约10倍差距,确保高级棋型优先
- 活四(100000)是冲四(10000)的10倍,因为活四必胜而冲四可防
总结
GameConstants虽然只有50行代码,但它奠定了整个项目的类型基础。好的常量设计能:
- 消除魔法数字,提高可读性
- 集中管理,方便修改
- 提供类型安全,减少bug
- 自文档化,降低理解成本