Game of 2048

Phase 1 — Core grid, rules & scoring

  • 4×4 board, slide/merge logic (left/right/up/down)
  • Spawn logic (A new 2 or 4 with configurable odds, e.g. 80% chance of spawning a 2, 20% chance of spawning a 4)
  • Deterministic update order; single-move application
  • Score tracking; win (tile 2048) and lose detection

Functional result: A small script runs a playable loop in the console: moves apply correctly, tiles spawn, score updates, and win/lose states are detected.


Phase 2 — Opponent types & CLI

  • CLI: 2048.py <opponent_type> via argparse
  • Opponent interface: choose_spawn(board) -> (row, col ,val)
  • Implement random and adversarial (choose worst legal spawn)
    • Random opponent: picks an empty cell at random and places a tile (2 or 4) using the spawn logic (like the normal 2048 game)

    • Adversarial opponent: tries to make the game harder; chooses the empty cell that will create the worst possible situation for the player

  • Optional --seed for reproducible behavior; validate type

Functional result: Running with random or adversarial changes difficulty; invalid types fall back to random; repeated runs with the same seed behave identically.


Phase 3 — GUI (Tkinter) gameplay

  • Window with 4×4 grid, colored tiles, score label
  • Keyboard input (arrows/WASD) driving moves
  • After each move: spawn via selected opponent, update UI
  • End-of-game modal when 2048 reached or no moves left

Functional result: Launching 2048.py random opens a responsive board where keys move tiles, score updates live, and a clear dialog appears on win/lose.


Phase 4 — Minimal UX polish

  • “New Game” button (reseed + clear board/score)
  • Simple animation timing (after) for slide/merge feel
  • Lightweight guardrails: ignore input during animation; cap FPS

Functional result: Players can restart instantly; moves feel smooth without jank; rapid key presses don’t break state, and overall play remains stable.