coding-horror/basic-computer-games · error · RuntimeException

Could not place any more ships

Error message

Could not place any more ships

What it means

Thrown as a RuntimeException by Ship.placeRandom() in the Battleship-style game after 1000 failed random attempts to fit the ship onto the Sea grid. Each attempt picks a random (x,y) start cell and one of four orientations, then calls place(). If none succeed, the sea is effectively saturated and the ship cannot fit. This is a constraint-violation: the total area demanded by all ships exceeds (or crowds out) the available board capacity given random placement.

Source

Thrown at 09_Battle/java/Ship.java:80

            offset = (y - startY) / orientY;
        }
        return hits.get(offset);
    };

    // Place the ship in the sea.
    // choose a random starting position, and a random direction
    // if that doesn't fit, keep picking different positions and directions
    public void placeRandom(Sea s) {
        Random random = new Random();
        for (int tries = 0 ; tries < 1000 ; ++tries) {
            int x = random.nextInt(s.size());
            int y = random.nextInt(s.size());
            int orient = random.nextInt(4);

            if (place(s, x, y, orient)) return;
        }

        throw new RuntimeException("Could not place any more ships");
    }

    // Attempt to fit the ship into the sea, starting from a given position and
    // in a given direction
    // This is by far the most complicated part of the program.
    // It will start at the position provided, and attempt to occupy tiles in the
    // requested direction. If it does not fit, either because of the edge of the
    // sea, or because of ships already in place, it will try to extend the ship
    // in the opposite direction instead. If that is not possible, it fails.
    public boolean place(Sea s, int x, int y, int orient) {
        if (placed) {
            throw new RuntimeException("Program error - placed ship " + id + " twice");
        }
        switch(orient) {
        case ORIENT_E:                 // east is increasing X coordinate
            orientX = 1; orientY = 0;
            break;
        case ORIENT_SE:                // southeast is increasing X and Y

View on GitHub (pinned to 5301155192)

Solutions

  1. Increase the Sea board size so total ship area fits comfortably.
  2. Reduce the number or sizes of ships placed.
  3. Raise the retry cap (1000) or switch placeRandom to a deterministic scan over every cell/orientation so a valid placement is found if one exists.
  4. Place larger ships before smaller ones to reduce fragmentation.

Example fix

// before
for (int tries = 0 ; tries < 1000 ; ++tries) {
    int x = random.nextInt(s.size());
    int y = random.nextInt(s.size());
    int orient = random.nextInt(4);
    if (place(s, x, y, orient)) return;
}
throw new RuntimeException("Could not place any more ships");

// after: exhaustive fallback before giving up
for (int x = 0; x < s.size(); x++)
  for (int y = 0; y < s.size(); y++)
    for (int orient = 0; orient < 4; orient++)
      if (place(s, x, y, orient)) return;
throw new RuntimeException("Could not place any more ships");
Defensive patterns

Strategy: validation

Validate before calling

// Java: ensure the ship fleet fits the board before placing
public static boolean fleetFits(int boardSize, List<Integer> shipSizes) {
  int total = shipSizes.stream().mapToInt(Integer::intValue).sum();
  return total * 2 <= boardSize * boardSize; // leave headroom for random placement
}

Try / catch

// Wrap placeRandom so a failed placement doesn't kill the game loop
try { ship.placeRandom(sea); }
catch (RuntimeException e) {
  if (e.getMessage().contains("Could not place")) { /* retry with larger board or fewer ships */ }
  else throw e;
}

Prevention

When it happens

Trigger: Calling placeRandom() on a Sea whose free cells are too few or too fragmented to hold the ship's size; many ships already placed leaving no contiguous run long enough; a board size configuration where ship sizes sum close to or above size*size.

Common situations: Tuning game config to too many ships or too-large ships for a small grid; the fleet-to-board ratio makes random placement statistically fail within 1000 tries even when a valid placement exists (unlucky clustering).

Related errors


AI-assisted analysis of coding-horror/basic-computer-games@5301155192 (2026-08-13). Data as JSON: /api/errors/8a6c10ffd4893811. Report an issue: GitHub.