Skip to content

Instantly share code, notes, and snippets.

@montlebalm
Created April 19, 2023 16:35
Show Gist options
  • Save montlebalm/ac2022adabb31f75cfa6e08a46cc0cda to your computer and use it in GitHub Desktop.
Save montlebalm/ac2022adabb31f75cfa6e08a46cc0cda to your computer and use it in GitHub Desktop.
t3-solidjs
import { Component, createSignal, For, JSX } from "solid-js";
//
// Types
//
type Mark = "x" | "o";
type Coord = `${number},${number}`;
//
// Constants
//
const coords: Coord[] = [
"0,0",
"0,1",
"0,2",
"1,0",
"1,1",
"1,2",
"2,0",
"2,1",
"2,2",
];
const checks: Coord[][] = [
// Rows
["0,0", "0,1", "0,2"],
["1,0", "1,1", "1,2"],
["2,0", "2,1", "2,2"],
// Columns
["0,0", "1,0", "2,0"],
["0,1", "1,1", "2,1"],
["0,2", "1,2", "2,2"],
// Diagonals
["0,0", "1,1", "2,2"],
["0,2", "1,1", "2,0"],
];
//
// App
//
const App: Component = (): JSX.Element => {
const [hasEnded, setHasEnded] = createSignal(false);
const [lastMark, setLastMark] = createSignal<Mark>();
const [board, setBoard] = createSignal<Record<string, Mark>>({});
const [winningCoords, setWinningCoords] = createSignal<Coord[]>([]);
const handleCellClick = (coord: Coord) => {
// Bail if the game has ended
if (hasEnded()) return;
// Bail if the cell is already marked
const prevMark = board()[coord];
if (prevMark) return;
const nextMark = lastMark() === "x" ? "o" : "x";
setBoard({
...board(),
[coord]: nextMark,
});
setLastMark(nextMark);
// Check if someone has won
score();
};
const score = () => {
for (const coords of checks) {
const [coord0, coord1, coord2] = coords;
const mark0 = board()[coord0];
const mark1 = board()[coord1];
const mark2 = board()[coord2];
// No sense scoring if there are too few marks
if (!mark0 || !mark1 || !mark2) continue;
if (mark0 === mark1 && mark1 === mark2) {
setWinningCoords(coords);
setHasEnded(true);
document.body.setAttribute("data-winner", "true");
return;
}
}
};
return (
<div class="ttt">
<div class="ttt-grid">
<For each={coords}>
{(coord) => (
<div
class="ttt-cell"
data-coord={coord}
data-mark={board()[coord]}
data-winner={winningCoords().includes(coord)}
onClick={() => handleCellClick(coord)}
/>
)}
</For>
</div>
</div>
);
};
export default App;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment