90 lines
2.0 KiB
TypeScript
90 lines
2.0 KiB
TypeScript
import {
|
|
Grid,
|
|
isInsideLarge,
|
|
getColor,
|
|
isInside,
|
|
Color,
|
|
isEmpty,
|
|
} from "./grid";
|
|
import { around4 } from "./point";
|
|
import {
|
|
getHeadX,
|
|
getHeadY,
|
|
nextSnake,
|
|
Snake,
|
|
snakeEquals,
|
|
snakeWillSelfCollide,
|
|
} from "./snake";
|
|
|
|
export const getAvailableRoutes = (
|
|
grid: Grid,
|
|
snake0: Snake,
|
|
onSolution: (snakes: Snake[], color: Color) => boolean
|
|
) => {
|
|
const openList: Snake[][] = [[snake0]];
|
|
const closeList: Snake[] = [];
|
|
|
|
while (openList.length) {
|
|
const c = openList.shift()!;
|
|
const [snake] = c;
|
|
|
|
closeList.push(snake);
|
|
|
|
const cx = getHeadX(snake);
|
|
const cy = getHeadY(snake);
|
|
|
|
for (let i = 0; i < around4.length; i++) {
|
|
const { x: dx, y: dy } = around4[i];
|
|
|
|
const nx = cx + dx;
|
|
const ny = cy + dy;
|
|
|
|
if (
|
|
isInsideLarge(grid, 1, nx, ny) &&
|
|
!snakeWillSelfCollide(snake, dx, dy)
|
|
) {
|
|
const nsnake = nextSnake(snake, dx, dy);
|
|
|
|
if (!closeList.some((s) => snakeEquals(nsnake, s))) {
|
|
const color = isInside(grid, nx, ny) && getColor(grid, nx, ny);
|
|
|
|
if (color && !isEmpty(color)) {
|
|
if (onSolution([nsnake, ...c.slice(0, -1)], color)) return;
|
|
} else {
|
|
if (!openList.some(([s]) => snakeEquals(nsnake, s))) {
|
|
const chain = [nsnake, ...c];
|
|
openList.push(chain);
|
|
openList.sort((a, b) => a.length - b.length);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
export const getAvailableInterestingRoutes = (
|
|
grid: Grid,
|
|
snake0: Snake,
|
|
onSolution: (snakes: Snake[], color: Color) => boolean,
|
|
n = snake0.length
|
|
) => {
|
|
const solutions: Snake[] = [];
|
|
|
|
getAvailableRoutes(grid, snake0, (snakes, color) => {
|
|
const [snake] = snakes;
|
|
|
|
for (let j = solutions.length; j--; ) {
|
|
let same = true;
|
|
for (let i = 0; i < n * 2; i++)
|
|
same = same && solutions[j][i] === snake[i];
|
|
|
|
if (same) return false;
|
|
}
|
|
|
|
solutions.push(snake);
|
|
|
|
return onSolution(snakes, color);
|
|
});
|
|
};
|