{"record":{"id":"8a6c10ffd4893811","repo":"coding-horror/basic-computer-games","slug":"could-not-place-any-more-ships","errorCode":null,"errorMessage":"Could not place any more ships","messagePattern":"Could not place any more ships","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"09_Battle/java/Ship.java","lineNumber":80,"sourceCode":"            offset = (y - startY) / orientY;\n        }\n        return hits.get(offset);\n    };\n\n    // Place the ship in the sea.\n    // choose a random starting position, and a random direction\n    // if that doesn't fit, keep picking different positions and directions\n    public void placeRandom(Sea s) {\n        Random random = new Random();\n        for (int tries = 0 ; tries < 1000 ; ++tries) {\n            int x = random.nextInt(s.size());\n            int y = random.nextInt(s.size());\n            int orient = random.nextInt(4);\n\n            if (place(s, x, y, orient)) return;\n        }\n\n        throw new RuntimeException(\"Could not place any more ships\");\n    }\n\n    // Attempt to fit the ship into the sea, starting from a given position and\n    // in a given direction\n    // This is by far the most complicated part of the program.\n    // It will start at the position provided, and attempt to occupy tiles in the\n    // requested direction. If it does not fit, either because of the edge of the\n    // sea, or because of ships already in place, it will try to extend the ship\n    // in the opposite direction instead. If that is not possible, it fails.\n    public boolean place(Sea s, int x, int y, int orient) {\n        if (placed) {\n            throw new RuntimeException(\"Program error - placed ship \" + id + \" twice\");\n        }\n        switch(orient) {\n        case ORIENT_E:                 // east is increasing X coordinate\n            orientX = 1; orientY = 0;\n            break;\n        case ORIENT_SE:                // southeast is increasing X and Y","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/coding-horror/basic-computer-games/blob/5301155192d91d74d337899cecc59dbda59c4c17/09_Battle/java/Ship.java#L62-L98","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","solutions":["Increase the Sea board size so total ship area fits comfortably.","Reduce the number or sizes of ships placed.","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.","Place larger ships before smaller ones to reduce fragmentation."],"exampleFix":"// before\nfor (int tries = 0 ; tries < 1000 ; ++tries) {\n    int x = random.nextInt(s.size());\n    int y = random.nextInt(s.size());\n    int orient = random.nextInt(4);\n    if (place(s, x, y, orient)) return;\n}\nthrow new RuntimeException(\"Could not place any more ships\");\n\n// after: exhaustive fallback before giving up\nfor (int x = 0; x < s.size(); x++)\n  for (int y = 0; y < s.size(); y++)\n    for (int orient = 0; orient < 4; orient++)\n      if (place(s, x, y, orient)) return;\nthrow new RuntimeException(\"Could not place any more ships\");","handlingStrategy":"validation","validationCode":"// Java: ensure the ship fleet fits the board before placing\npublic static boolean fleetFits(int boardSize, List<Integer> shipSizes) {\n  int total = shipSizes.stream().mapToInt(Integer::intValue).sum();\n  return total * 2 <= boardSize * boardSize; // leave headroom for random placement\n}","typeGuard":null,"tryCatchPattern":"// Wrap placeRandom so a failed placement doesn't kill the game loop\ntry { ship.placeRandom(sea); }\ncatch (RuntimeException e) {\n  if (e.getMessage().contains(\"Could not place\")) { /* retry with larger board or fewer ships */ }\n  else throw e;\n}","preventionTips":["Place the largest ships first to reduce fragmentation.","Keep the sum of ship lengths well below board area (e.g. <= 25-30%).","Use an exhaustive scan fallback before declaring failure so a valid placement is always found if one exists."],"tags":["java","game-logic","random-placement","constraint-violation"],"backgroundTag":null,"analyzedSha":"5301155192d91d74d337899cecc59dbda59c4c17","analyzedAt":"2026-08-13T19:29:00.979Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}