HarmonyOS 鸿蒙6.0实战开发项目--AI 五子棋对战 App
HarmonyOS 鸿蒙6.0实战开发项目–AI 五子棋对战 App
本项目是一个基于 HarmonyOS ArkTS + ArkUI 开发的鸿蒙五子棋 App,项目名为 WzqGame。项目包含登录、注册、本地人机对战、棋盘尺寸切换、黑白执棋选择、AI 自动落子、胜负判定、悔棋、音效开关、棋盘最大化和事件日志等功能,适合用来练习 HarmonyOS 原生应用中的状态管理、自定义棋盘绘制、游戏规则封装和简单 AI 策略实现。
功能如下:
- 用户登录或注册
- 15x15 与 30x30 棋盘切换
- 选择执黑先手或执白后手
- 本地 AI 自动对弈
- 五子连线胜负判定
- 平局判断
- 悔棋与重新开始
- 棋盘最大化、缩放和平移
- 黑白落子音效
- 对局事件日志
一、系统架构总览
项目采用 HarmonyOS Stage 模型开发,整体可以拆成五层:
| 层级 | 主要文件 | 职责 |
|---|---|---|
| 页面层 | Index.ets |
登录注册、对局设置、棋盘页面、结果弹窗、用户交互 |
| 棋盘渲染层 | BoardCell.ets、Index.ets 中的 BoardCell Builder |
棋盘网格、星位、棋子、最后落子标记 |
| 规则模型层 | GameTypes.ets、GameLogic.ets、GameState.ets |
棋子类型、游戏状态、落子记录、胜负和平局判断 |
| AI 决策层 | LocalGomokuAI.ets |
候选点筛选、攻防评分、AI 落子选择 |
| 公共能力层 | GameConstants.ets、AudioManager.ets |
棋盘参数、星位配置、缩放参数、落子音效 |
核心数据流如下:
用户点击棋盘
-> Index.ets 校验当前状态和落子位置
-> 更新 boardData 与 moveHistory
-> GameLogic.determineGameStatus() 判断胜负
-> 未结束时切换 currentTurn
-> 如果轮到 AI,LocalGomokuAI.chooseMove() 计算落点
-> @State 驱动棋盘、状态栏、日志实时刷新
登录注册目前使用页面本地状态保存账户信息:
| 状态 | 用途 |
|---|---|
isLoggedIn |
控制登录页和首页切换 |
authAccount |
当前输入的手机号/邮箱 |
authPassword |
当前输入的密码 |
registeredAccount |
本地注册账号 |
registeredPassword |
本地注册密码 |
二、系统演示截图
1. 登录页
登录页只保留手机号/邮箱、密码、登录、注册和忘记密码入口,页面风格沿用原项目的浅色背景、白色面板和蓝色主按钮。

2. 注册页
注册页包含手机号/邮箱、密码和确认密码,提交时完成基础校验。

3. 对局设置页
对局设置页可以选择棋盘尺寸和执棋颜色,进入游戏后由黑方先手。

4. AI 对战棋盘
棋盘页面展示当前回合、步数、玩家与 AI 棋色、悔棋、重新开始、最大化和音效开关。

5. 对局状态与日志
事件日志记录开局、AI 落点、悔棋和胜负结果,方便观察整局对弈过程。

三、系统详细介绍
1. 登录与注册
登录注册逻辑位于 Index.ets,没有单独拆路由页面,而是在现有入口页中通过 isLoggedIn 控制展示登录注册页或游戏首页。
核心状态:
@State isLoggedIn: boolean = false;
@State authMode: AuthMode = AuthMode.LOGIN;
@State authAccount: string = '';
@State authPassword: string = '';
@State authConfirmPassword: string = '';
@State registeredAccount: string = '';
@State registeredPassword: string = '';
注册时主要处理三类校验:
- 手机号/邮箱不能为空
- 密码不能为空
- 确认密码不能为空,且两次密码一致
登录时校验账号和密码不能为空。本地已注册账号后,会继续校验账号和密码是否匹配。登录成功后设置:
this.currentAccount = account;
this.isLoggedIn = true;
这里先使用本地页面状态模拟登录流程,后续接后端时可以把 handleLogin() 和 handleRegister() 替换为真实接口请求。
2. 对局设置
对局设置集中在 SetupPanel() 中,页面保留三个核心信息:
- 棋盘尺寸
- 执棋颜色
- 开始对战
棋盘尺寸支持 15x15 和 30x30:
private switchBoardSize(size: number): void {
this.selectedBoardSize = size === 30 ? 30 : 15;
if (this.phase === GamePhase.SETUP) {
this.resetBoard(this.selectedBoardSize);
}
}
执棋颜色支持黑方先手和白方后手。如果玩家选择白方,进入游戏后会先触发 AI 黑棋落子。
3. 棋盘渲染
棋盘渲染主要在 Index.ets 的 StaticBoard()、ScalableBoard() 和 BoardCell() 中完成。每个交叉点通过 ForEach(getIndices(this.boardSize)) 生成,按行列渲染网格、星位和棋子。
棋盘单元格主要包含:
- 横向网格线
- 纵向网格线
- 星位标记
- 黑白棋子
- 最后落子红点标记
棋盘样式配置来自 GameConstants.ets:
export const BOARD_LAYOUT = {
padding: 15,
board15: {
cellSize: 22,
pieceSize: 20
},
board30: {
baseCellSize: 12,
basePieceSize: 10
}
};
30x30 棋盘和最大化模式下支持缩放和平移,方便在手机屏幕上查看大棋盘。
4. 游戏状态与落子流程
游戏状态由 GamePhase 和 GameStatus 共同控制:
enum GamePhase {
SETUP = 'setup',
PLAYING = 'playing',
OVER = 'over'
}
一次玩家落子的核心流程:
private handleCellClick(row: number, col: number): void {
if (!this.canPlace(row, col)) {
return;
}
const placed = this.placePiece(row, col, this.playerPiece, true);
if (placed && this.gameStatus === GameStatus.PLAYING) {
this.queueAiMove();
}
}
placePiece() 会复制棋盘、写入棋子、记录历史、播放音效、判断胜负,并在对局未结束时切换回合。
5. 胜负判定
胜负判定封装在 GameLogic.ets 中,核心思路是以最后落子点为中心,向四个方向双向统计连续同色棋子数量。
四个方向:
export const DIRECTIONS: Position[] = [
{ row: 0, col: 1 },
{ row: 1, col: 0 },
{ row: 1, col: 1 },
{ row: 1, col: -1 }
];
判断逻辑:
const total = positiveCount + negativeCount + 1;
if (total >= this.config.winCondition) {
return true;
}
这种写法只围绕最后一步落子检查,不需要每次遍历整张棋盘,适合五子棋这类实时交互场景。
6. 本地 AI 决策
AI 逻辑封装在 LocalGomokuAI.ets。AI 不依赖网络服务,直接根据当前棋盘状态计算落点。
AI 决策大致分为五步:
- 扫描棋盘生成候选落点
- 优先寻找 AI 能直接获胜的位置
- 检查玩家是否存在必须阻挡的连线
- 对候选点进行攻防评分
- 选择综合分最高的位置落子
核心入口:
const move: AIMove | null = this.ai.chooseMove(
this.boardData,
this.aiPiece,
this.playerPiece
);
评分时会同时考虑进攻和防守,避免 AI 只顾自己连子而忽略玩家威胁。
7. 悔棋、日志和音效
悔棋逻辑位于 undoLastRound()。由于是人机对战,悔棋时默认撤销最近两步,也就是玩家一步和 AI 一步,让棋局回到玩家可继续选择的位置。
事件日志通过 eventLogs 维护,最多保留 8 条:
this.eventLogs.push(`${timeText} ${content}`);
if (this.eventLogs.length > 8) {
this.eventLogs.shift();
}
音效由 AudioManager.ets 管理,黑白棋分别使用 black_piece.mp3 和 white_piece.mp3。页面上通过 Toggle 控制音效开关。
四、核心模型说明
| 模型 | 类型 | 说明 |
|---|---|---|
PieceType |
enum |
空位、黑子、白子 |
GameStatus |
enum |
进行中、黑方胜、白方胜、平局 |
MoveRecord |
interface |
单步落子记录 |
GameConfig |
interface |
棋盘尺寸、胜利条件、悔棋限制 |
Position |
interface |
棋盘坐标 |
AIMove |
interface |
AI 落点和落子原因 |
这些模型把棋盘数据、游戏规则和页面展示拆开,后续如果扩展联机对战、难度选择或战绩统计,可以继续基于这些结构增加字段。
五、数据流向示例
以“玩家执黑开始一局”为例:
用户登录
-> 进入对局设置页
-> 选择 15x15 棋盘和执黑先手
-> 点击开始对战
-> resetBoard() 初始化棋盘
-> 玩家点击棋盘落黑子
-> GameLogic 判断是否获胜
-> currentTurn 切换到白方
-> LocalGomokuAI 计算白方落点
-> AI 落白子
-> 页面状态、棋盘、日志同步刷新
这个流程覆盖了 HarmonyOS 应用中常见的页面状态切换、列表渲染、自定义组件、交互反馈和业务逻辑封装。
六、开发中的关键处理
1. 棋盘数据不可直接原地改
落子时先复制 boardData,再替换整份棋盘数据:
const nextBoard = this.cloneBoard(this.boardData);
nextBoard[row][col] = piece;
this.boardData = nextBoard;
这样能让 ArkUI 更稳定地感知状态变化并刷新棋盘。
2. 胜负判断只检查最后一步
每次落子后只围绕最后落点检查四个方向,不做全棋盘扫描。这样 30x30 棋盘也能保持较轻的计算量。
3. AI 落子需要延迟反馈
AI 使用 setTimeout() 延迟落子,让用户能感受到“玩家落子 -> AI 思考 -> AI 落子”的过程,不会显得页面瞬间跳变。
4. 30x30 棋盘要支持缩放
手机屏幕直接展示 30x30 棋盘会比较密集,所以项目给大棋盘和最大化模式加入 PinchGesture 和 PanGesture,支持双指缩放和三指拖动。
5. 页面文案保持克制
登录注册页只保留账号、密码、确认密码、登录、注册和忘记密码,没有加入第三方登录、验证码倒计时或宣传式文案,页面更接近真实 App 的功能页。
七、适合继续扩展的方向
这个项目可以继续扩展:
- 登录状态持久化
- 接入后端登录注册接口
- AI 难度选择
- 人人双人对战模式
- 对局计时
- 战绩统计
- 棋谱回放
- 禁手规则
- 联机对战
- 棋盘主题切换
如果想继续提高完整度,可以优先做 AI 难度选择、战绩统计和棋谱回放,这些功能和五子棋 App 的使用场景最接近。
八、项目总结
AI 五子棋对战项目覆盖了 HarmonyOS 实战开发中比较典型的能力:
- ArkUI 页面搭建
- ArkTS 状态管理
- 本地登录注册
- 自定义棋盘渲染
- 手势缩放和平移
- 音频播放控制
- 游戏规则封装
- 本地 AI 决策
- 对局日志和结果弹窗
它的页面数量不多,但能把 UI、状态、模型、算法和交互反馈串起来。对于正在学习 HarmonyOS 的同学来说,这类小型游戏项目很适合用来理解 ArkTS 状态驱动 UI 的开发方式。
九、源码获取
想获取代码请点击此链接或下方链接
https://ycc123666.oss-cn-beijing.aliyuncs.com/img/87ce0de2f2d8d0baab5b6aa8c3aebdab.jpg
更多推荐


所有评论(0)