CASE STUDY

Online Minesweeper Platform

3 min read·451 words·Beginner

Asked at

1 candidate report in Nov 2025

How to use this case study

SDE-2 / Mid

Design the game model (board, mines, revealed cells, flags), the reveal algorithm (flood fill for zeros) and the APIs.

SDE-3 / Senior

Keep game state on the server to prevent cheating, persist games to resume later, handle concurrency (one active session), and store leaderboard times.

Staff / Principal

Discuss scaling to many concurrent games, fairness (first click never a mine), daily challenges and anti-cheat.


0) Problem Restatement

Amazon asked: design an online Minesweeper platform. Players start games at different difficulty levels (e.g., Beginner 9×9 with 10 mines, Expert 30×16 with 99 mines), reveal and flag cells with low latency, can resume unfinished games later, and compete on leaderboards for the fastest wins.


1) Game Rules (quick recap)

  • Hidden mines on a grid. Revealing a mine = lose.
  • Revealing a safe cell shows the number of adjacent mines (0–8).
  • Revealing a 0 automatically reveals its neighbors (a flood fill), since none of them can be mines.
  • Win when all non-mine cells are revealed.


2) Who Holds the Truth? The Server

If the mine positions are sent to the client, a player can read them (cheat). So:

  • The server generates and keeps the mine layout (never sent to the client until the game ends).
  • The client sends actions (reveal(r, c), flag(r, c)), and the server returns the newly revealed cells and numbers.
  • First click safety: generate the mines after the first click, excluding that cell (and often its neighbors).


3) Architecture

Architecture Diagram

flowchart LR
    P["Player browser"] -->|"reveal / flag (HTTP or WebSocket)"| API["Game API - stateless"]
    API --> ST[("Game state - Redis, active games")]
    API --> DB[("Postgres - finished games, users")]
    API --> LB[("Leaderboards - sorted sets per difficulty")]
  • Active game state is small (Expert: 480 cells, a few hundred bytes as bitsets), so keep it in Redis with a TTL (e.g., 7 days) for resuming, and write a snapshot to the DB on finish.
  • The API is stateless, so any server can handle any move.


4) Data Model

game: game_id, user_id, difficulty, rows, cols, mines (bitset, server-only), revealed (bitset),
      flagged (bitset), status (playing|won|lost), started_at, finished_at, moves_count, version

5) Reveal Algorithm (server side)

from collections import deque

def reveal(game, r, c):
    if game.status != "playing" or game.revealed[r][c] or game.flagged[r][c]:
        return []
    if game.mines[r][c]:
        game.status = "lost"
        return [("mine", r, c)]
    opened, q = [], deque([(r, c)])
    game.revealed[r][c] = True
    while q:
        x, y = q.popleft()
        n = game.adjacent_mines(x, y)
        opened.append((n, x, y))
        if n == 0:                                   # flood fill through zeros
            for dx in (-1, 0, 1):
                for dy in (-1, 0, 1):
                    nx, ny = x + dx, y + dy
                    if game.inside(nx, ny) and not game.revealed[nx][ny] and not game.flagged[nx][ny]:
                        game.revealed[nx][ny] = True
                        q.append((nx, ny))
    if game.safe_cells_left() == 0:
        game.status = "won"
    return opened

BFS avoids deep recursion on big empty areas. The adjacent-mine counts can be precomputed when mines are placed.


6) Concurrency, Timing and Leaderboards

  • One active session per game: moves carry a version, and the server applies them with a conditional update (compare-and-set in Redis via a Lua script), so double clicks or two tabs can't corrupt the state.
  • Timing: the server records the start time (on first reveal) and the finish time. The server clock is authoritative, which stops time manipulation.
  • Leaderboards: on a win, add the time to a sorted set per difficulty (lower is better), plus daily and weekly boards.
  • Anti-cheat: server-side mines already stop the obvious cheat. Also flag impossible times (faster than humanly possible) and bot-like click patterns.


7) Wrap-Up

Keep the mine layout only on the server (generated after a safe first click), and let clients send reveal and flag actions to a stateless API that updates compact bitset game state in Redis with version checks. Reveal uses BFS flood fill through zero cells, finished games are saved to the DB, and server-timed wins go into per-difficulty sorted-set leaderboards with basic anti-cheat checks.

More Case Studies

Practice with a Mock Interview

Apply what you learned in a live system design mock interview with our AI interviewer.

Start System Design Interview →