A browser-based tic-tac-toe widget built from scratch with an unbeatable AI opponent and online multiplayer. Features four game modes, immutable state management, a Cloudflare Worker relay with KV persistence, and room-code matchmaking.
Features
- Unbeatable AI (Hard) — minimax algorithm explores the full game tree for perfect play; Easy mode picks moves at random
- Online multiplayer — room-code matchmaking via Cloudflare Worker relay with Workers KV for cross-instance state sharing
- Session persistence — sessionStorage-backed rejoin; refresh or change tabs without losing your game
- Four game modes — vs AI (Easy), vs AI (Hard), local PvP, and online PvP
- State-driven rendering — immutable game state with a single render path; DOM always reflects current state
- Win line highlighting — winning triplet cells get a highlighted background for instant visual feedback
Architecture
TTTEngine (pure logic, zero DOM)
├─ createGame() → fresh state object
├─ makeMove() → immutable move + win/draw detection
├─ checkWin() → scans 8 win lines against board
├─ getBestMove() → easy=random, hard=minimax (recursive tree search)
└─ minimax() → +10 / -10 / 0 scoring, in-place mutate & undo
TTTWidget (UI controller)
├─ mount() → bootstraps widget into DOM container
├─ renderBoard() → redraws 9 cells from current state
├─ handleClick() → validates, applies move, triggers AI or POST
├─ updateStatus() → turn indicator, win/draw messages
└─ pollRoom() → 500ms polling for opponent moves in online mode
Cloudflare Worker (multiplayer relay)
├─ POST /room/create → generates 4-char room code
├─ POST /room/join/:code → joins as O, supports X-Player-Mark rejoin
├─ POST /room/:code/move → validates turn, applies move server-side
├─ GET /room/:code → polls current board state
└─ POST /room/:code/rematch → resets board, swaps X/O