← Questions
React Battleship board that tracks sunk ships
0
I was asked this
No reports yet. Sign in to say where you were asked it.
Build a single-player Battleship-style board in React: just the board and the logic that decides which ships are sunk. No opponent, no turns, no networking. The board is an N x N grid and a fixed list of ships is given up front, each occupying known cells. Clicking a cell cycles its state, and a status panel shows each ship as sunk or not.
Interface
Unless you agree on a different interface with the interviewer, assume:
type Cell = "empty" | "white" | "red"; // white = miss, red = hit
type Ship = { id: string; cells: Array<[row: number, col: number]> };
function Board(props: { size: number; ships: Ship[] }): JSX.Element;
function nextState(c: Cell): Cell; // empty -> white -> red -> empty
function isSunk(ship: Ship, cells: Map<string, Cell>): boolean; // every cell of the ship is red
- Clicking any cell cycles it with
nextState. A ship is sunk exactly when all of its cells arered; sunk status is derived from the cells, never stored separately. - A Reset button returns every cell to
empty.
Example
ships: A at (0,0) (0,1); B at (2,2) (2,3) (2,4)
click (0,0) twice -> (0,0) red panel: A not sunk, B not sunk
click (0,1) twice -> (0,1) red panel: A sunk, B not sunk
click (0,1) once -> (0,1) empty panel: A not sunk (sunk is recomputed, not latched)
click (5,5) once -> (5,5) white a miss marked on a cell with no ship
Constraints
- Board around 10 x 10 with about five ships of length 2 to 5; in-memory only.
- Game logic (
nextState,isSunk) must be testable without React.
Clarifying questions
- Can ships change after mount?
- Can the user mark cells that hold no ship?
- What does
redon a non-ship cell mean? - Are overlapping ships allowed, and does a shared red cell count for both?
- Is there an "all sunk" win message?
- Is keyboard and screen-reader support required?
What a strong answer covers
- Sorting the data into fixed input (ships, size), changing state (cell marks), and derived values (sunk status), and storing only the middle one.
- A sparse map keyed by
"row,col"where untouched cells default toempty. - The click handler as a functional update (
setCells(prev => ...)) with an immutable copy, so fast clicks never read stale state. - Sunk status computed with
useMemofrom the cells and ships; reset just clears the map. - Component split:
Boardowns state,GridandCellButtonrender,StatusPanelreads derived values; stable callbacks and memoized cells for larger boards. - Defined behaviour for overlapping or out-of-bounds ship cells (validate on mount).
Follow-ups
- Add a "ship sunk!" toast or an "all ships sunk" banner without extra mutable state.
- A 1000 x 1000 grid: virtualized rendering and incremental sunk counts.
- Full keyboard access and ARIA grid semantics.
- Which parts get pure unit tests and which need component tests?
No official answer yet. Write yours on the right and run it.
Nothing published yet.
Sign in to submit your code; every attempt is kept here.
Write and test your solution herePython in your browser, the question's tests level by level, every submission kept for you.Sign in to start coding
