game/tests/engine.test.js

130 lines
4.1 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* 规则引擎测试:node --test tests/ */
const { test } = require('node:test');
const assert = require('node:assert');
const E = require('../js/engine.js');
// 直接往棋盘上摆子,用于构造测试局面(绕过轮流落子)
function setStones(game, color, coords) {
for (const [x, y] of coords) game.board[y][x] = color;
}
test('黑先并且落子后交替行棋', () => {
const g = E.createGame();
assert.strictEqual(g.currentPlayer, E.BLACK);
const r = E.place(g, 7, 7);
assert.strictEqual(r.ok, true);
assert.strictEqual(g.currentPlayer, E.WHITE);
E.place(g, 8, 8);
assert.strictEqual(g.currentPlayer, E.BLACK);
});
test('横向五连判胜', () => {
const g = E.createGame();
setStones(g, E.BLACK, [[3, 7], [4, 7], [5, 7], [6, 7]]);
g.currentPlayer = E.BLACK;
const r = E.place(g, 7, 7);
assert.strictEqual(r.win, true);
assert.strictEqual(g.winner, E.BLACK);
assert.strictEqual(g.gameOver, true);
assert.deepStrictEqual(g.winningLine, [
{ x: 3, y: 7 }, { x: 4, y: 7 }, { x: 5, y: 7 }, { x: 6, y: 7 }, { x: 7, y: 7 },
]);
});
test('纵向五连判胜', () => {
const g = E.createGame();
setStones(g, E.WHITE, [[7, 3], [7, 4], [7, 5], [7, 6]]);
g.currentPlayer = E.WHITE;
const r = E.place(g, 7, 7);
assert.strictEqual(r.win, true);
assert.strictEqual(g.winner, E.WHITE);
});
test('斜向(左上到右下)五连判胜', () => {
const g = E.createGame();
setStones(g, E.BLACK, [[3, 3], [4, 4], [5, 5], [6, 6]]);
g.currentPlayer = E.BLACK;
const r = E.place(g, 7, 7);
assert.strictEqual(r.win, true);
});
test('斜向(左下到右上)五连判胜', () => {
const g = E.createGame();
setStones(g, E.BLACK, [[3, 10], [4, 9], [5, 8], [6, 7]]);
g.currentPlayer = E.BLACK;
const r = E.place(g, 7, 6);
assert.strictEqual(r.win, true);
assert.strictEqual(g.winningLine.length, 5);
});
test('长连(六连)同样判胜', () => {
const g = E.createGame();
setStones(g, E.BLACK, [[3, 5], [4, 5], [5, 5], [6, 5], [8, 5]]);
g.currentPlayer = E.BLACK;
const r = E.place(g, 7, 5);
assert.strictEqual(r.win, true);
assert.strictEqual(g.winningLine.length, 6);
});
test('四连不判胜', () => {
const g = E.createGame();
setStones(g, E.BLACK, [[3, 7], [4, 7], [5, 7], [6, 7]]);
g.currentPlayer = E.BLACK;
const r = E.place(g, 9, 9); // 与四连无关的落子
assert.strictEqual(r.win, undefined);
assert.strictEqual(g.gameOver, false);
});
test('非法落子被拒绝:已占用', () => {
const g = E.createGame();
E.place(g, 7, 7);
const r = E.place(g, 7, 7);
assert.strictEqual(r.ok, false);
});
test('非法落子被拒绝:越界', () => {
const g = E.createGame();
assert.strictEqual(E.place(g, -1, 0).ok, false);
assert.strictEqual(E.place(g, 0, -1).ok, false);
assert.strictEqual(E.place(g, 15, 0).ok, false);
assert.strictEqual(E.place(g, 0, 15).ok, false);
});
test('对局结束后拒绝继续落子', () => {
const g = E.createGame();
setStones(g, E.BLACK, [[3, 7], [4, 7], [5, 7], [6, 7]]);
g.currentPlayer = E.BLACK;
E.place(g, 7, 7);
const r = E.place(g, 10, 10);
assert.strictEqual(r.ok, false);
assert.strictEqual(r.reason, '游戏已结束');
});
test('棋盘下满判平局', () => {
const g = E.createGame();
// 用 (x + 2y) mod 4 的双色填充,任意方向连续同色不超过 2,不会误判五连
for (let y = 0; y < E.SIZE; y++) {
for (let x = 0; x < E.SIZE; x++) {
if (x === 14 && y === 14) continue;
const v = ((x + 2 * y) % 4 + 4) % 4;
g.board[y][x] = v === 0 || v === 1 ? E.BLACK : E.WHITE;
}
}
g.currentPlayer = E.BLACK;
const r = E.place(g, 14, 14);
assert.strictEqual(r.draw, true);
assert.strictEqual(g.gameOver, true);
assert.strictEqual(g.winner, 0);
});
test('落子历史被完整记录', () => {
const g = E.createGame();
E.place(g, 7, 7);
E.place(g, 8, 8);
E.place(g, 7, 8);
assert.strictEqual(g.moveHistory.length, 3);
assert.deepStrictEqual(g.moveHistory[0], { x: 7, y: 7, player: E.BLACK });
assert.deepStrictEqual(g.moveHistory[1], { x: 8, y: 8, player: E.WHITE });
assert.deepStrictEqual(g.moveHistory[2], { x: 7, y: 8, player: E.BLACK });
});