Katkat

Build a React naval board

WaymoFrontend Engineer · Technical Screen

Last updated

This question evaluates a candidate's ability to design frontend state and UI logic—specifically React component structure, state management, click-handling semantics, and derived sunk-detection logic for a Battleship-style board.

Build a simplified, single-player Battleship-style game board in React. There is no opponent, no turn-taking, and no networking — you are implementing the board UI and the sunk-detection logic only.

The board is an N x N grid (e.g. 10 x 10). You are given a fixed list of ships up front, where each ship occupies a known set of cell coordinates. Each cell can be clicked to cycle through three visual states:

  • empty — nothing placed
  • white — a miss
  • red — a hit on a ship segment

A status panel lists every ship as sunk or not sunk. A ship is sunk only when every coordinate it occupies is currently marked red.

Constraints & Assumptions

  • Board size is configurable but small in practice (10 x 10 ⇒ 100 cells).
  • The ship list is fixed and provided as input (no placement UI). A typical game has ~5 ships of lengths 2–5.
  • Clicking a cell cycles its state deterministically: empty → white → red → empty.
  • Ship "sunk" status is derived from the current cell states — it is not separately stored or mutated.
  • Rendering must be kept separate from game logic so the sunk-detection can be unit-tested without React.
  • This is an in-memory exercise: no persistence, no backend, no animation requirements.

The Problem

Design and implement the React board. In your answer, cover all five of the following:

  1. Component structure for the grid and the status panel.
  2. State management for cell states and ship definitions.
  3. The click handler that updates a cell's state.
  4. The sunk-detection logic for each ship.
  5. Edge cases: repeated clicks, reset behavior, overlapping/invalid ship coordinates, and keeping rendering logic separate from game logic.

Clarifying Questions to Ask

  • Is the ship list truly fixed at mount, or can ships be added/removed at runtime?
  • Should a cell that isn't part of any ship still be clickable (i.e. can the user mark misses anywhere)?
  • What should red on a non-ship cell mean — an invalid "hit," or just a colored marker with no game meaning?
  • Are overlapping ships allowed, and if so, how should a shared cell's red count toward both ships?
  • Is there a win condition / "all ships sunk" message, or only the per-ship panel?
  • Do we need keyboard accessibility and ARIA roles, or is mouse-only acceptable for this exercise?

Hints

Hint 1

Where to start: Before writing any state, sort each piece of information into one of three buckets: what's fixed input you never mutate, what genuinely changes as the user clicks, and what you could always recompute from the second bucket. Getting this split right is most of the problem.

Hint 2

Data structure for cell state: Most of the 100 cells are never touched. Does your representation have to enumerate all of them, or could the "untouched" case be the default rather than something you store? Also think about how you'll address one cell consistently, whatever shape you choose.

Hint 3

Sunk detection: Reconsider whether "sunk" needs to live in state at all. If you can answer "is this ship sunk?" by looking only at the current cell states, what data does that check need — and what does keeping it derived buy you when the board resets?

Hint 4

Click cycling: Treat the three-way state change as its own self-contained rule, independent of React. Then think about how to apply it on click so that two fast clicks land on the right state and you never read a stale value — which form of the state setter guarantees that?

Follow-up questions

  • How would you add a "ship sunk!" toast or an "all ships sunk — you win" banner without storing extra mutable state?
  • If the grid were `1000 x 1000`, what would you change in rendering (virtualization) and in sunk-detection (incremental updates) to keep clicks responsive?
  • How would you make the board fully keyboard-accessible and screen-reader friendly?
  • How would you test this — which logic deserves pure unit tests vs. which needs a rendered React component test?