You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

战舰游戏舰船随机放置:子类实例化与间距控制技术问题

解决方案:战舰游戏舰船放置优化与碰撞校验

一、消除代码冗余:通用舰船放置方法

当前每个舰船单独写放置方法的问题在于重复了随机坐标、边界检查、网格更新的核心逻辑。可以抽象出通用方法,通过传入舰船类型、长度、数组索引等参数,复用所有放置逻辑:

通用放置方法实现

// 通用舰船放置方法,支持所有Ship子类
private <T extends Ship> void placeShip(Class<T> shipClass, int shipLength, int shipIndex, char[][] selfGrid) {
    int xCor, yCor;
    boolean isShipPlaced = false;
    // 随机生成舰船方向
    int shipOrientation = Math.random() > 0.5 ? VERTICAL : HORIZONTAL;

    do {
        xCor = (int) (Math.random() * 9) + 1;
        yCor = (int) (Math.random() * 9) + 1;

        // 先判断边界,再校验位置合法性
        if (shipOrientation == VERTICAL && yCor + shipLength <= BattleshipSystem.GRID_LENGTH) {
            if (isPositionValid(selfGrid, xCor, yCor, shipLength, VERTICAL)) {
                playerShips[shipIndex] = createShipInstance(shipClass, xCor, yCor, xCor, yCor + shipLength);
                updateGrid(selfGrid, xCor, yCor, shipLength, VERTICAL);
                isShipPlaced = true;
            }
        } else if (shipOrientation == HORIZONTAL && xCor + shipLength <= BattleshipSystem.GRID_LENGTH) {
            if (isPositionValid(selfGrid, xCor, yCor, shipLength, HORIZONTAL)) {
                playerShips[shipIndex] = createShipInstance(shipClass, xCor, yCor, xCor + shipLength, yCor);
                updateGrid(selfGrid, xCor, yCor, shipLength, HORIZONTAL);
                isShipPlaced = true;
            }
        }
    } while (!isShipPlaced);
}

// 单独抽出生成Ship实例的方法,避免反射逻辑混杂
private <T extends Ship> T createShipInstance(Class<T> shipClass, int x1, int y1, int x2, int y2) {
    try {
        return shipClass.getConstructor(int.class, int.class, int.class, int.class)
                .newInstance(x1, y1, x2, y2);
    } catch (Exception e) {
        throw new RuntimeException("Failed to create ship instance", e);
    }
}

// 单独抽出网格更新方法
private void updateGrid(char[][] grid, int x, int y, int length, int orientation) {
    if (orientation == VERTICAL) {
        for (int dy = y; dy < y + length; dy++) {
            grid[dy][x] = SHIP;
        }
    } else {
        for (int dx = x; dx < x + length; dx++) {
            grid[y][dx] = SHIP;
        }
    }
}

调用示例

// 放置航母
placeShip(Carrier.class, Carrier.CARRIER_LENGTH, 0, selfGrid);
// 放置战列舰
placeShip(Battleship.class, Battleship.BATTLESHIP_LENGTH, 1, selfGrid);
// 放置潜艇
placeShip(Submarine.class, Submarine.SUBMARINE_LENGTH, 2, selfGrid);
// 放置巡逻艇
placeShip(PatrolBoat.class, PatrolBoat.PATROL_BOAT_LENGTH, 3, selfGrid);

如果不想用反射,也可以用工厂模式替代createShipInstance方法,通过类型判断生成对应舰船实例,避免反射异常风险。

二、实现舰船不重叠且不相邻的校验

核心是检查舰船占据的所有格子,以及这些格子周围8个方向的相邻格子是否已存在SHIP。编写如下校验方法:

private boolean isPositionValid(char[][] grid, int x, int y, int length, int orientation) {
    if (orientation == VERTICAL) {
        // 覆盖舰船本身及上下左右斜向的所有相邻区域
        for (int dy = y - 1; dy <= y + length; dy++) {
            for (int dx = x - 1; dx <= x + 1; dx++) {
                // 过滤网格外的坐标
                if (dx >= 0 && dx < BattleshipSystem.GRID_LENGTH && dy >= 0 && dy < BattleshipSystem.GRID_LENGTH) {
                    if (grid[dy][dx] == SHIP) {
                        return false;
                    }
                }
            }
        }
    } else { // 水平方向
        for (int dx = x - 1; dx <= x + length; dx++) {
            for (int dy = y - 1; dy <= y + 1; dy++) {
                if (dx >= 0 && dx < BattleshipSystem.GRID_LENGTH && dy >= 0 && dy < BattleshipSystem.GRID_LENGTH) {
                    if (grid[dy][dx] == SHIP) {
                        return false;
                    }
                }
            }
        }
    }
    return true;
}

注意事项

  • 原代码中的边界判断yCor + Carrier.CARRIER_LENGTH < BattleshipSystem.GRID_LENGTH需修正为<=,避免舰船超出网格索引范围(比如网格长度为10时,索引0-9,yCor=5+长度5=10会越界)
  • 校验范围包含了舰船周围一圈的所有格子,确保满足“至少一格间距”的要求

额外优化建议

  • 给抽象父类Ship添加getLength()抽象方法,每个子类实现该方法返回自身长度,这样通用放置方法可直接调用ship.getLength(),无需手动传入长度参数
  • 若随机放置多次仍无法找到有效位置,可添加重试次数限制,避免极端情况下的死循环

内容的提问来源于stack exchange,提问作者okaycomputer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 11:26:19