2023-07-12 14:15:53 -04:00
|
|
|
import { render_and_copy } from "./common.tsx";
|
2023-07-09 20:51:15 -04:00
|
|
|
|
|
|
|
type Square = "x" | "o" | "empty";
|
|
|
|
type Row = [Square, Square, Square];
|
|
|
|
type Board = [Row, Row, Row];
|
|
|
|
type SquareIdx = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
|
|
|
|
|
|
|
|
const empty_row: Row = ["empty", "empty", "empty"];
|
|
|
|
const empty_board: Board = [empty_row, empty_row, empty_row];
|
|
|
|
//{ board: [r1, r2, r3] }
|
|
|
|
|
|
|
|
const square_of_turn = (turn: number): Square => (turn % 2 == 0 ? "x" : "o");
|
|
|
|
function game_over([[s1, s2, s3], [s4, s5, s6], [s7, s8, s9]]: Board): boolean {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: strike out and such
|
2023-07-12 14:15:53 -04:00
|
|
|
const Board = ({ board, turn = 0 }: { board: Board; turn?: number }) => (
|
2023-07-09 20:51:15 -04:00
|
|
|
<div class="state">
|
|
|
|
{game_over(board) ? (
|
|
|
|
<div class="whose-turn game-over">Game over!</div>
|
|
|
|
) : (
|
|
|
|
<div class="whose-turn">It's {square_of_turn(turn)}'s turn!</div>
|
|
|
|
)}
|
|
|
|
<div class="board">
|
|
|
|
<Row board={board} idx={0} turn={turn} />
|
|
|
|
<Row board={board} idx={1} turn={turn} />
|
|
|
|
<Row board={board} idx={2} turn={turn} />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
|
2023-07-12 14:15:53 -04:00
|
|
|
const Row = ({
|
|
|
|
board,
|
|
|
|
idx,
|
|
|
|
turn,
|
|
|
|
}: {
|
|
|
|
board: Board;
|
|
|
|
idx: number;
|
|
|
|
turn: number;
|
|
|
|
}) => (
|
2023-07-09 20:51:15 -04:00
|
|
|
<div class="row">
|
2023-07-12 14:15:53 -04:00
|
|
|
<Cell board={board} idx={(idx + 0) as SquareIdx} turn={turn} />
|
|
|
|
<Cell board={board} idx={(idx + 1) as SquareIdx} turn={turn} />
|
|
|
|
<Cell board={board} idx={(idx + 2) as SquareIdx} turn={turn} />
|
2023-07-09 20:51:15 -04:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
|
2023-07-12 14:15:53 -04:00
|
|
|
const Cell = ({
|
|
|
|
board,
|
|
|
|
idx,
|
|
|
|
turn,
|
|
|
|
}: {
|
|
|
|
board: Board;
|
|
|
|
idx: SquareIdx;
|
|
|
|
turn: number | "game over";
|
|
|
|
}) => {
|
|
|
|
if (turn == "game over") {
|
|
|
|
return <div class="cell empty"></div>;
|
|
|
|
}
|
2023-07-09 20:51:15 -04:00
|
|
|
const square = get_square(board, idx);
|
2023-07-12 14:15:53 -04:00
|
|
|
return square == "empty" ? (
|
2023-07-09 20:51:15 -04:00
|
|
|
<details class="cell empty">
|
|
|
|
<summary></summary>
|
|
|
|
<SuccBoard board={board} idx={idx} turn={turn} />
|
|
|
|
</details>
|
|
|
|
) : (
|
2023-07-12 14:15:53 -04:00
|
|
|
<div class={`cell ${square}`}>{square}</div>
|
2023-07-09 20:51:15 -04:00
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2023-07-12 14:15:53 -04:00
|
|
|
const SuccBoard = ({
|
|
|
|
board,
|
|
|
|
idx,
|
|
|
|
turn,
|
|
|
|
}: {
|
|
|
|
board: Board;
|
|
|
|
idx: SquareIdx;
|
|
|
|
turn: number;
|
|
|
|
}) => {
|
2023-07-09 20:51:15 -04:00
|
|
|
const square = square_of_turn(turn);
|
|
|
|
|
2023-07-12 14:15:53 -04:00
|
|
|
return <Board board={set_square(board, idx, square)} turn={turn + 1} />;
|
2023-07-09 20:51:15 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
function get_square(board: Board, idx: SquareIdx): Square {
|
|
|
|
return board[Math.floor(idx / 3)][idx % 3];
|
|
|
|
}
|
|
|
|
|
|
|
|
function set_square(board: Board, idx: SquareIdx, to: Square): Board {
|
|
|
|
const new_board = JSON.parse(JSON.stringify(board)) as Board;
|
|
|
|
|
|
|
|
new_board[Math.floor(idx / 3)][idx % 3] = to;
|
|
|
|
|
|
|
|
return new_board;
|
|
|
|
}
|
|
|
|
|
2023-07-12 14:15:53 -04:00
|
|
|
render_and_copy(<Board board={set_square(empty_board, 4, "x")} />);
|