64 lines
2.3 KiB
JavaScript
64 lines
2.3 KiB
JavaScript
/* AI 行为测试:node --test tests/ai.test.js */
|
||
const { test } = require('node:test');
|
||
const assert = require('node:assert');
|
||
const E = require('../js/engine.js');
|
||
const AI = require('../js/ai.js');
|
||
|
||
function setStones(game, color, coords) {
|
||
for (const [x, y] of coords) game.board[y][x] = color;
|
||
}
|
||
|
||
test('空盘首着落天元', () => {
|
||
const g = E.createGame();
|
||
assert.deepStrictEqual(AI.nextMove(g, E.BLACK), { x: 7, y: 7 });
|
||
});
|
||
|
||
test('能一手取胜时直接取胜', () => {
|
||
const g = E.createGame();
|
||
// 白方横向四连(x=4..7, y=5),左端被黑封堵,唯一成五点是 (8,5)
|
||
setStones(g, E.WHITE, [[4, 5], [5, 5], [6, 5], [7, 5]]);
|
||
setStones(g, E.BLACK, [[3, 5]]);
|
||
assert.deepStrictEqual(AI.nextMove(g, E.WHITE), { x: 8, y: 5 });
|
||
});
|
||
|
||
test('对方冲四时必防守', () => {
|
||
const g = E.createGame();
|
||
// 黑方横向四连(x=3..6, y=9),左端 (2,9) 已被白封堵,白必须在 (7,9) 挡
|
||
setStones(g, E.BLACK, [[3, 9], [4, 9], [5, 9], [6, 9]]);
|
||
setStones(g, E.WHITE, [[2, 9]]);
|
||
assert.deepStrictEqual(AI.nextMove(g, E.WHITE), { x: 7, y: 9 });
|
||
});
|
||
|
||
test('对方活三时封挡端点', () => {
|
||
const g = E.createGame();
|
||
// 黑方两端开阔的活三,白应落在 (5,7) 或 (9,7) 之一
|
||
setStones(g, E.BLACK, [[6, 7], [7, 7], [8, 7]]);
|
||
const mv = AI.nextMove(g, E.WHITE);
|
||
assert.ok(
|
||
(mv.x === 5 && mv.y === 7) || (mv.x === 9 && mv.y === 7),
|
||
`期望封挡 (5,7) 或 (9,7),实际落在 (${mv.x},${mv.y})`
|
||
);
|
||
});
|
||
|
||
test('己方活三优先于防守对方眠二', () => {
|
||
const g = E.createGame();
|
||
// 白有活二 (4,8)(5,8),黑只有零散两子;白应继续连子而非远端防守
|
||
setStones(g, E.WHITE, [[4, 8], [5, 8]]);
|
||
setStones(g, E.BLACK, [[10, 3], [3, 11]]);
|
||
const mv = AI.nextMove(g, E.WHITE);
|
||
const nearOwn = Math.abs(mv.x - 4) + Math.abs(mv.y - 8) <= 4
|
||
|| Math.abs(mv.x - 5) + Math.abs(mv.y - 8) <= 4;
|
||
assert.ok(nearOwn, `期望在己方活二附近行棋,实际落在 (${mv.x},${mv.y})`);
|
||
});
|
||
|
||
test('返回的点永远是空位', () => {
|
||
const g = E.createGame();
|
||
setStones(g, E.BLACK, [[7, 7], [8, 8], [6, 8]]);
|
||
setStones(g, E.WHITE, [[7, 8], [8, 6], [6, 6]]);
|
||
g.currentPlayer = E.WHITE;
|
||
for (let i = 0; i < 20; i++) {
|
||
const mv = AI.nextMove(g);
|
||
assert.strictEqual(g.board[mv.y][mv.x], E.EMPTY);
|
||
}
|
||
});
|