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

