HarmonyOS 小游戏《对战五子棋》开发第8篇 - GomokuEngine核心引擎设计(三):五子连珠判定算法
·
从一个点出发,向四个方向延伸——五子棋胜负判定的核心算法
截图如下:

checkWin算法详解
checkWin(row: number, col: number, player: number): boolean {
const directions: number[][] = [
[0, 1], // 水平 →
[1, 0], // 垂直 ↓
[1, 1], // 主对角线 ↘
[1, -1] // 副对角线 ↙
];
for (const dir of directions) {
let count = 1; // 包含当前落子
// 正方向计数
for (let i = 1; i < 5; i++) {
const r = row + dir[0] * i;
const c = col + dir[1] * i;
if (r < 0 || r >= BOARD_SIZE || c < 0 || c >= BOARD_SIZE) break;
if (this.board[r][c] === player) count++;
else break;
}
// 反方向计数
for (let i = 1; i < 5; i++) {
const r = row - dir[0] * i;
const c = col - dir[1] * i;
if (r < 0 || r >= BOARD_SIZE || c < 0 || c >= BOARD_SIZE) break;
if (this.board[r][c] === player) count++;
else break;
}
if (count >= 5) return true;
}
return false;
}
算法思路
五子棋的获胜条件是:同一颜色的棋子在水平、垂直或对角线方向上连续排列5个或以上。
判定算法的核心思想:
- 以最新落子位置为中心
- 沿4个方向(水平、垂直、两条对角线)分别检查
- 每个方向向正反两个方向延伸,统计连续同色棋子数
- 如果任一方向的总数≥5,则获胜
四个方向的向量
方向1: [0, 1] → 水平方向(行不变,列递增)
方向2: [1, 0] ↓ 垂直方向(行递增,列不变)
方向3: [1, 1] ↘ 主对角线(行列同时递增)
方向4: [1, -1] ↙ 副对角线(行递增,列递减)
用向量表示方向的好处是统一的计算公式:
- 正方向:
r = row + dir[0] * i,c = col + dir[1] * i - 反方向:
r = row - dir[0] * i,c = col - dir[1] * i
图解计数过程
假设黑棋在(7,7)落子,向左有2个黑棋,向右有2个黑棋:
水平方向 [0,1]:
←反方向 正方向→
○ ○ ● ←(7,7)→ ● ○ ○
count=1
←延伸 延伸→
count=3 count=5 → 获胜!
为什么只需要检查4个方向
五子棋有8个方向(上下左右+4个对角线),但每对相反方向是同一条线。检查4个方向的正反两侧就覆盖了所有8个方向:
↖ ↑ ↗
\ | /
← — ● — →
/ | \
↙ ↓ ↘
4个方向 × 2侧 = 8个方向
为什么只需检查最近一手
这是算法的关键优化——只检查最新落子位置的胜负。
原因:之前的状态没有产生五连(否则游戏已结束),新落子只可能在其所在的4条线上形成五连。因此不需要全盘扫描。
时间复杂度:O(4 × 4 × 2) = O(32) ≈ O(1),常数时间!
边界处理
if (r < 0 || r >= BOARD_SIZE || c < 0 || c >= BOARD_SIZE) break;
每次延伸都要检查是否越界。这是防止数组越界的标准做法。
AIPlayer中的checkWin
AIPlayer中有一个独立的checkWin实现(因为AI不持有GomokuEngine实例):
private checkWin(board: number[][], row: number, col: number, player: number): boolean {
const directions: number[][] = [[0, 1], [1, 0], [1, 1], [1, -1]];
for (const dir of directions) {
let count = 1;
for (let i = 1; i < 5; i++) {
const r = row + dir[0] * i;
const c = col + dir[1] * i;
if (r < 0 || r >= BOARD_SIZE || c < 0 || c >= BOARD_SIZE) break;
if (board[r][c] === player) count++;
else break;
}
for (let i = 1; i < 5; i++) {
const r = row - dir[0] * i;
const c = col - dir[1] * i;
if (r < 0 || r >= BOARD_SIZE || c < 0 || c >= BOARD_SIZE) break;
if (board[r][c] === player) count++;
else break;
}
if (count >= 5) return true;
}
return false;
}
逻辑完全一致,区别在于接收board参数而非使用this.board。
总结
五子连珠判定算法是游戏引擎中最精巧的部分之一:
- 以点带面:只检查最新落子,O(1)复杂度
- 向量方向:4个方向向量统一处理
- 正反延伸:每个方向检查正反两侧
- 边界安全:每次延伸都验证越界
这个算法是棋类游戏胜负判定的经典范式,可以推广到四子棋、六子棋等变体。
更多推荐


所有评论(0)