refactor: improved line checks
This commit is contained in:
parent
975d363769
commit
d4d428b577
|
|
@ -193,68 +193,75 @@ export function removePieceFromBoard(host: Entity<BoopState>, part: Entity<BoopP
|
|||
});
|
||||
}
|
||||
|
||||
const DIRECTIONS: [number, number][] = [
|
||||
[0, 1],
|
||||
[1, 0],
|
||||
[1, 1],
|
||||
[1, -1],
|
||||
];
|
||||
|
||||
export function* linesThrough(r: number, c: number): Generator<number[][]> {
|
||||
for (const [dr, dc] of DIRECTIONS) {
|
||||
const minStart = -(WIN_LENGTH - 1);
|
||||
for (let offset = minStart; offset <= 0; offset++) {
|
||||
const startR = r + offset * dr;
|
||||
const startC = c + offset * dc;
|
||||
const endR = startR + (WIN_LENGTH - 1) * dr;
|
||||
const endC = startC + (WIN_LENGTH - 1) * dc;
|
||||
|
||||
if (startR < 0 || startR >= BOARD_SIZE || startC < 0 || startC >= BOARD_SIZE) continue;
|
||||
if (endR < 0 || endR >= BOARD_SIZE || endC < 0 || endC >= BOARD_SIZE) continue;
|
||||
|
||||
const line: number[][] = [];
|
||||
for (let i = 0; i < WIN_LENGTH; i++) {
|
||||
line.push([startR + i * dr, startC + i * dc]);
|
||||
}
|
||||
yield line;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function* allLines(): Generator<number[][]> {
|
||||
const seen = new Set<string>();
|
||||
for (let r = 0; r < BOARD_SIZE; r++) {
|
||||
for (let c = 0; c < BOARD_SIZE; c++) {
|
||||
for (const line of linesThrough(r, c)) {
|
||||
const key = line.map(p => p.join(',')).join(';');
|
||||
if (!seen.has(key)) {
|
||||
seen.add(key);
|
||||
yield line;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function hasWinningLine(positions: number[][]): boolean {
|
||||
const posSet = new Set(positions.map(p => `${p[0]},${p[1]}`));
|
||||
for (const line of allLines()) {
|
||||
if (line.every(([lr, lc]) => posSet.has(`${lr},${lc}`))) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function checkGraduation(host: Entity<BoopState>, player: PlayerType): number[][][] {
|
||||
const board = getBoardRegion(host);
|
||||
const partsMap = board.partsMap.value;
|
||||
const positions: number[][] = [];
|
||||
const posSet = new Set<string>();
|
||||
|
||||
for (const key in partsMap) {
|
||||
const part = partsMap[key] as Entity<BoopPart>;
|
||||
if (part.value.player === player && part.value.pieceType === 'kitten') {
|
||||
positions.push(part.value.position);
|
||||
posSet.add(`${part.value.position[0]},${part.value.position[1]}`);
|
||||
}
|
||||
}
|
||||
|
||||
const winningLines: number[][][] = [];
|
||||
|
||||
for (let r = 0; r < BOARD_SIZE; r++) {
|
||||
for (let c = 0; c <= BOARD_SIZE - WIN_LENGTH; c++) {
|
||||
const line = [];
|
||||
for (let i = 0; i < WIN_LENGTH; i++) {
|
||||
line.push([r, c + i]);
|
||||
}
|
||||
if (line.every(([lr, lc]) => positions.some(([pr, pc]) => pr === lr && pc === lc))) {
|
||||
winningLines.push(line);
|
||||
}
|
||||
for (const line of allLines()) {
|
||||
if (line.every(([lr, lc]) => posSet.has(`${lr},${lc}`))) {
|
||||
winningLines.push(line);
|
||||
}
|
||||
}
|
||||
|
||||
for (let c = 0; c < BOARD_SIZE; c++) {
|
||||
for (let r = 0; r <= BOARD_SIZE - WIN_LENGTH; r++) {
|
||||
const line = [];
|
||||
for (let i = 0; i < WIN_LENGTH; i++) {
|
||||
line.push([r + i, c]);
|
||||
}
|
||||
if (line.every(([lr, lc]) => positions.some(([pr, pc]) => pr === lr && pc === lc))) {
|
||||
winningLines.push(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let r = 0; r <= BOARD_SIZE - WIN_LENGTH; r++) {
|
||||
for (let c = 0; c <= BOARD_SIZE - WIN_LENGTH; c++) {
|
||||
const line = [];
|
||||
for (let i = 0; i < WIN_LENGTH; i++) {
|
||||
line.push([r + i, c + i]);
|
||||
}
|
||||
if (line.every(([lr, lc]) => positions.some(([pr, pc]) => pr === lr && pc === lc))) {
|
||||
winningLines.push(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let r = WIN_LENGTH - 1; r < BOARD_SIZE; r++) {
|
||||
for (let c = 0; c <= BOARD_SIZE - WIN_LENGTH; c++) {
|
||||
const line = [];
|
||||
for (let i = 0; i < WIN_LENGTH; i++) {
|
||||
line.push([r - i, c + i]);
|
||||
}
|
||||
if (line.every(([lr, lc]) => positions.some(([pr, pc]) => pr === lr && pc === lc))) {
|
||||
winningLines.push(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return winningLines;
|
||||
}
|
||||
|
||||
|
|
@ -312,39 +319,3 @@ export function checkWinner(host: Entity<BoopState>): WinnerType {
|
|||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function hasWinningLine(positions: number[][]): boolean {
|
||||
for (let r = 0; r < BOARD_SIZE; r++) {
|
||||
for (let c = 0; c <= BOARD_SIZE - WIN_LENGTH; c++) {
|
||||
const line = [];
|
||||
for (let i = 0; i < WIN_LENGTH; i++) line.push([r, c + i]);
|
||||
if (line.every(([lr, lc]) => positions.some(([pr, pc]) => pr === lr && pc === lc))) return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (let c = 0; c < BOARD_SIZE; c++) {
|
||||
for (let r = 0; r <= BOARD_SIZE - WIN_LENGTH; r++) {
|
||||
const line = [];
|
||||
for (let i = 0; i < WIN_LENGTH; i++) line.push([r + i, c]);
|
||||
if (line.every(([lr, lc]) => positions.some(([pr, pc]) => pr === lr && pc === lc))) return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (let r = 0; r <= BOARD_SIZE - WIN_LENGTH; r++) {
|
||||
for (let c = 0; c <= BOARD_SIZE - WIN_LENGTH; c++) {
|
||||
const line = [];
|
||||
for (let i = 0; i < WIN_LENGTH; i++) line.push([r + i, c + i]);
|
||||
if (line.every(([lr, lc]) => positions.some(([pr, pc]) => pr === lr && pc === lc))) return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (let r = WIN_LENGTH - 1; r < BOARD_SIZE; r++) {
|
||||
for (let c = 0; c <= BOARD_SIZE - WIN_LENGTH; c++) {
|
||||
const line = [];
|
||||
for (let i = 0; i < WIN_LENGTH; i++) line.push([r - i, c + i]);
|
||||
if (line.every(([lr, lc]) => positions.some(([pr, pc]) => pr === lr && pc === lc))) return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -332,7 +332,7 @@ describe('Boop - helper functions', () => {
|
|||
|
||||
const lines = checkGraduation(state, 'white');
|
||||
expect(lines.length).toBe(1);
|
||||
expect(lines[0]).toEqual([[2, 0], [1, 1], [0, 2]]);
|
||||
expect(lines[0]).toEqual([[0, 2], [1, 1], [2, 0]]);
|
||||
});
|
||||
|
||||
it('should not detect line with mixed piece types', () => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue