Skip to content

mirmashhouri/2048

Repository files navigation

2048

A fully-featured clone of the classic 2048 puzzle game, built with React, TypeScript, and Vite.

You can try the live demo here: 👉 https://2048-pro.vercel.app

Features

  • Configurable rules — adjust board size, win tile, initial tile count, and spawn probabilities before every game via the settings screen
  • Four-directional moves — keyboard arrow keys or on-screen buttons
  • Tile spawning — a 2 (90%) or 4 (10%) spawns after every valid move
  • Win / lose detection — overlay shown when you reach 2048 or run out of moves
  • AI suggestion — offline Expectimax algorithm (depth 4) recommends the best next move
  • Auto-play — let the AI play the game continuously
  • Score tracking — current score and all-time best persisted in localStorage

Tech Stack

Layer Choice
UI React 19
Language TypeScript 5
Bundler Vite 5
Styles SCSS Modules
Testing Vitest

Getting Started

Prerequisites

  • Node.js 18+
  • npm 9+

Install dependencies

npm install

Run in development mode

npm run dev

Open http://localhost:5173 in your browser.

Build for production

npm run build

Output is written to dist/.

Preview the production build

npm run preview

Running Tests

# Watch mode
npm test

# Single run (CI)
npm run test:run

Tests live alongside their source files in __tests__/ directories.

Project Structure

src/
├── components/
│   ├── Board/          # Grid rendering
│   ├── ConfigForm/     # Game setup screen
│   ├── Controls/       # Move buttons, suggest & auto-play
│   ├── GameHeader/     # Score, best, new-game, settings
│   ├── GameOverlay/    # Win / lose overlay
│   ├── GameScreen/     # Main game layout
│   └── Tile/           # Individual tile with colour mapping
├── game/
│   ├── ai/             # AI strategy and its config
│   ├── engine/         # Board operations and core game primitives
│   └── rules/          # Game rules, defaults, and spawn behaviour
├── utils/
│   ├── loadJsonConfig.ts # Shared JSON config loading helper
│   ├── random.ts         # Shared random helper functions
│   └── storage.ts        # localStorage best-score persistence
└── hooks/
    ├── useGame.ts       # Central game state
    ├── useAutoPlay.ts   # AI auto-play loop
    └── useKeyboard.ts   # Arrow-key bindings

How the AI Works

The AI uses an Expectimax search with the following design:

  • Algorithm — Expectimax, alternating between player nodes (max) and chance nodes (expected value over tile spawns)
  • Search depth — 4 half-moves; gives a good balance between move quality and response time
  • Chance node capping — when there are many empty cells the branching factor is capped at 6 randomly sampled positions to keep the AI responsive in the early game
  • Heuristics (scored and summed):
    • Empty cells — more free space means more flexibility
    • Highest tile — rewards progress toward the win tile
    • Monotonicity — rewards boards where tile values decrease toward a corner
    • Smoothness — penalises large differences between adjacent tiles

All AI parameters are defined in ai.config.json and can be tuned without touching code:

{
  "maxDepth": 4,          // how many half-moves ahead to search (higher = smarter but slower)
  "maxEmptySample": 6,    // max empty cells sampled per chance node (limits branching)
  "weights": {
    "emptyCount": 270,    // reward for each empty cell (flexibility)
    "maxTile": 100,       // reward for the highest tile (progress toward win)
    "monotonicity": 70,   // reward for tiles decreasing toward a corner (ordered layout)
    "smoothness": 50      // penalty for large differences between adjacent tiles
  }
}

No network calls or API keys are required; everything runs locally in the browser.

Default Game Rules

The defaults are defined in game.config.json. Edit that file to change the out-of-the-box values before building.

{
  "boardSize": 4,             // N×N grid size (e.g. 5 → 5×5)
  "initialTileValues": [2],   // tile values used at game start (e.g. [2, 4])
  "initialTileCountMin": 2,   // fewest tiles placed at start
  "initialTileCountMax": 8,   // most tiles placed at start
  "spawnDistribution": [      // weighted spawn chances (auto-normalised)
    { "value": 2, "probability": 0.9 },
    { "value": 4, "probability": 0.1 }
  ],
  "winTile": 2048             // tile value that wins the game (e.g. 4096)
}

About

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages