1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/** @jsxImportSource https://esm.sh/react */
import React, { useState, useEffect } from "https://esm.sh/react";
import { createRoot } from "https://esm.sh/react-dom/client";
import { renderToString } from "https://esm.sh/react-dom/server";
// Hexagon component
const Hexagon = ({ x, y, size, fill, onClick, isEdge }) => {
const points = [];
for (let i = 0; i < 6; i++) {
const angle = (Math.PI / 3) * i;
points.push(`${x + size * Math.cos(angle)},${y + size * Math.sin(angle)}`);
}
return (
<polygon
points={points.join(" ")}
fill={fill}
stroke={isEdge ? "red" : "black"}
strokeWidth={isEdge ? "3" : "1"}
onClick={onClick}
/>
);
};
// Game component
function Game() {
const gridSize = 5; // This creates a grid with 61 hexagons
const hexSize = 30;
const [grid, setGrid] = useState([]);
const [catPosition, setCatPosition] = useState(null);
const [gameStatus, setGameStatus] = useState("playing");
// Initialize grid
const initializeGame = () => {
const newGrid = [];
for (let q = -gridSize; q <= gridSize; q++) {
for (let r = Math.max(-gridSize, -q - gridSize); r <= Math.min(gridSize, -q + gridSize); r++) {
const s = -q - r;
const isEdge = Math.abs(q) === gridSize || Math.abs(r) === gridSize || Math.abs(s) === gridSize;
newGrid.push({ q, r, s, state: "empty", isEdge });
}
}
setGrid(newGrid);
const centerHex = newGrid.find(h => h.q === 0 && h.r === 0 && h.s === 0);
setCatPosition(centerHex);
setGameStatus("playing");
};
useEffect(initializeGame, []);
// Convert cube coordinates to pixel coordinates
const cubeToPixel = (q, r) => {
const x = hexSize * (3/2 * q);
const y = hexSize * (Math.sqrt(3)/2 * q + Math.sqrt(3) * r);
return { x, y };
};
// Check if the cat can escape
const checkCatEscape = () => {
return catPosition && catPosition.isEdge;
};
// Move the cat
const moveCat = () => {
if (gameStatus !== "playing") return;
const neighbors = [
{ q: 1, r: 0, s: -1 }, { q: 1, r: -1, s: 0 }, { q: 0, r: -1, s: 1 },
{ q: -1, r: 0, s: 1 }, { q: -1, r: 1, s: 0 }, { q: 0, r: 1, s: -1 }
];
const possibleMoves = neighbors
.map(n => ({ q: catPosition.q + n.q, r: catPosition.r + n.r, s: catPosition.s + n.s }))
.filter(pos => {
const hex = grid.find(h => h.q === pos.q && h.r === pos.r && h.s === pos.s);
return hex && hex.state === "empty";
});
if (possibleMoves.length === 0) {
setGameStatus("playerWin");
return;
}
// Find the move closest to an edge
const newPos = possibleMoves.reduce((closest, move) => {
const closestEdgeDist = Math.min(
gridSize - Math.abs(closest.q),
gridSize - Math.abs(closest.r),
gridSize - Math.abs(closest.s)
);
const moveDist = Math.min(
gridSize - Math.abs(move.q),
gridSize - Math.abs(move.r),
gridSize - Math.abs(move.s)
);
return moveDist < closestEdgeDist ? move : closest;
});
const newCatPosition = grid.find(h => h.q === newPos.q && h.r === newPos.r && h.s === newPos.s);
setCatPosition(newCatPosition);