# Tic-Tac-Toe vs CPU — Implementation Plan A polished, mobile-friendly tic-tac-toe game (X vs O) playable in the browser against a random-move CPU opponent. Pure HTML/CSS/JS — no build step, no dependencies. Open `index.html` directly in a browser to play. ## 1. Project Structure ``` game1/ ├── index.html # Page structure (board, scoreboard, status, overlay) ├── style.css # All styling: glassmorphism dark theme, animations ├── game.js # Game logic: state, win detection, CPU, scoring, FX └── docs/ ├── PLAN.md # This document └── mockup.svg # UI mockup (open in a browser to view) ``` ## 2. Visual Design Research (Dribbble/Figma/CodePen examples) shows the current popular style for tic-tac-toe: **dark glassmorphism with neon accents**, frosted panels, soft glows, and confetti celebrations on wins. - **Background**: deep gradient (dark navy → violet) with two soft blurred colored blobs (cyan + magenta) for depth. - **Panels**: frosted glass cards — `background: rgba(255,255,255,0.06)`, `backdrop-filter: blur(14px)`, 1px translucent white border, soft shadow. (Blur kept modest for mobile performance.) - **Colors**: - X (player) — neon cyan `#22d3ee` - O (CPU) — neon pink/magenta `#f472b6` - Text: white / muted gray - **Typography**: system font stack, bold title, tabular numerals for scores. - **Mockup**: see `docs/mockup.svg` (open in a browser) for the envisioned look — dark glass panels, neon cyan X / pink O with glow, gradient title. - **Layout (top → bottom)**: 1. Title: "Tic-Tac-Toe" with subtle gradient text 2. Scoreboard: three glass chips — You (X) · CPU (O) · Draws 3. Status bar: "Your turn" / "CPU is thinking…" / result text 4. Board: 3×3 grid of glass cells 5. Buttons: "New Game" (primary) and "Reset Scores" (ghost) ## 3. Mobile-Friendliness - `` - Board width: `min(88vw, 340px)`; cells are large touch targets (≥ 72px on phones). - `touch-action: manipulation` on buttons/cells to kill double-tap zoom delay. - No hover-only interaction: hover glow is a desktop enhancement only; taps work everywhere. Use `:active` press feedback. - Layout uses flex column, centered, max-width 420px — looks like a mobile app on desktop too. - `user-select: none` on the board to avoid text selection while tapping fast. - Test: 360px-wide viewport, fast repeated taps, orientation change. ## 4. Game Rules - Standard 3×3 tic-tac-toe. Player is **X**, CPU is **O**. - Player always starts the round with X (keeps it simple and predictable). - Click/tap an empty cell to place your mark. - CPU responds on a random empty cell after a **600 ms "thinking" delay** (feels natural, shows the "CPU is thinking…" status). - Win: 3 in a row (8 winning lines). Draw: board full with no winner. - After a round ends, a result overlay appears; "Play Again" starts a fresh round (board clears, scores persist). ## 5. Scoring - Track **You**, **CPU**, and **Draws** across rounds. - Persisted in `localStorage` (key `ttt-scores`) so scores survive reloads. - "Reset Scores" button zeroes them (with a short confirm-less toast feedback). - Score chips animate a quick pop when the value changes. ## 6. Game-Over Reactions - **Winning line**: an SVG line is drawn across the three winning cells with a stroke-dashoffset animation (draws itself in ~400 ms). - **Result overlay**: frosted glass modal fades/scales in with: - Win → "You Win! 🎉" + confetti burst (DOM particles, ~40 pieces, random colors/velocities, fall + fade over ~1.8 s, then removed). - Loss → "CPU Wins" + a subtle red-tinted shake of the board. - Draw → "It's a Draw" + neutral pulse. - Overlay has a single big "Play Again" button. - Small micro-feedback during play: - Marks pop in with a scale+fade animation (150 ms). - Empty cells glow faintly on hover (desktop) and brighten on `:active`. - Status bar text cross-fades on turn change; "CPU is thinking…" pulses. ## 7. JavaScript Architecture (game.js) Single file, plain functions + one state object: ``` state = { board: Array(9).fill(null), // null | 'X' | 'O' turn: 'X', // 'X' = player, 'O' = CPU gameOver: false, scores: { you: 0, cpu: 0, draws: 0 } } ``` Modules (sections in the file): 1. **DOM refs** — cells, status, score chips, overlay, buttons. 2. **Win detection** — `WIN_LINES` = 8 combos; `checkWinner(board)` returns `{winner, line}` or `{winner: 'draw'}` or `null`. 3. **Player move** — `onCellTap(i)`: ignore if occupied/game over/CPU turn; place X, render, check end; else schedule CPU. 4. **CPU move** — `cpuMove()`: after 600 ms, pick a random empty index, place O, render, check end. 5. **Render** — `renderMark(i, mark)` (pop animation), `renderStatus()`, `renderScores()`, `drawWinLine(line)` (SVG overlay on the board). 6. **Round end** — `endRound(result)`: update + persist scores, show overlay with appropriate FX (confetti / shake / pulse). 7. **Confetti** — `burstConfetti()`: create N absolutely-positioned divs with random transforms, animate via CSS transitions, remove after finish. 8. **Reset** — `newRound()` (clear board, player first), `resetScores()`. 9. **Init** — load scores from localStorage, build board DOM, bind events. ## 8. Implementation Steps 1. `index.html` — semantic structure, viewport meta, SVG defs for win line. 2. `style.css` — theme tokens (CSS custom properties), background, glass panels, board grid, marks (X/O drawn with CSS or inline SVG for crispness), animations (pop, pulse, shake, confetti fall), overlay, responsive tweaks. 3. `game.js` — implement sections 1–9 above. 4. Manual test pass: - Win all 8 line types (play through scenarios). - Draw scenario. - Rapid tapping (no double placement, no CPU overlap). - Scores persist across reload; reset works. - 360px viewport: no overflow, big touch targets, no zoom on tap. 5. Polish: check animation smoothness on a mid-range phone if available. ## 9. Hosting the App The app is three static files, so any static file server works. The goal is a one-line start, no config files, no build step. **Primary option — Python (already installed, zero setup):** ```bash python3 -m http.server 8000 ``` Run from the `game1/` folder. It binds to all network interfaces by default, so the game is immediately reachable: - **Same machine**: http://localhost:8000 - **Same network (LAN)**: http://\:8000 (find the IP with `hostname -I` or `ip addr`) - **Internet**: forward port 8000 in the router/firewall, or put the machine behind a reverse proxy. For public exposure, prefer caddy (see below) and keep the raw port closed otherwise. **Alternative — Caddy (nicest for internet exposure, auto-TLS with a domain):** ```bash caddy file-server --root . --listen :8000 ``` **Alternative — Node (if Python is unavailable):** ```bash npx serve -l 8000 ``` Notes: - These dev servers are fine for LAN / home use. For a public internet endpoint, use caddy behind a domain (it handles TLS automatically) and do not expose the raw port to the internet with a bare dev server. - No deploy step: the folder *is* the app — copy it anywhere and serve it. ## 10. Non-Goals (kept simple on purpose) - No minimax / unbeatable AI (CPU is random, as requested). - No sound effects, no multi-language support, no user-vs-user mode. - No framework, no bundler — the game is three files.