Игра Морской бой - перекрытие кораблей

Я пишу простую игру про боевой корабль на Java, используя библиотеку ACM. После запуска игры корабли должны быть размещены на холсте в случайных местах, но проблема в том, что корабли могут прикрывать друг друга, а это в игре запрещено. Как я могу избежать размещения кораблей друг на друге?

Мой код:

private void putSmallShips() {
    for (int i = 0; i < SMALL_SHIP_QUANTITY; i++){
        smallShip = new GRect(SMALL_SHIP_WIDTH, SHIP_HEIGHT);
        int x = rgen.nextInt(10, 510);
        int y = rgen.nextInt(10, 510);
        while (true){
            gobj = getElementAt(x, y);
            if (gobj == null) break;
            x = rgen.nextInt(10, 510);
            y = rgen.nextInt(10, 510);
        }
        smallShip.setLocation(x, y);
        add(smallShip);
    }
}

private void putMiddleShips() {
    for (int i = 0; i < MIDDLE_SHIP_QUANTITY; i++){
        middleShip = new GRect(MIDDLE_SHIP_WIDTH, SHIP_HEIGHT);
        int x = rgen.nextInt(10, 530);
        int y = rgen.nextInt(10, 530);

        while (true){
            gobj = getElementAt(x, y);
            if (gobj == null) break;
            System.out.println("opa!");
            x = rgen.nextInt(10, 530);
            y = rgen.nextInt(10, 530);
        }
        x = x + i * 10;
        y = y + i * 10;
        middleShip.setLocation(x, y);
        add(middleShip);
    }
}

private void putBigShips() {
    for (int i = 0; i < BIG_SHIP_QUANTITY; i++){
        bigShip = new GRect(BIG_SHIP_WIDTH, SHIP_HEIGHT);
        int x = rgen.nextInt(10, 550);
        int y = rgen.nextInt(10, 550);
        while (true){
            gobj = getElementAt(x, y);
            if (gobj == null) break;
            x = rgen.nextInt(10, 550);
            y = rgen.nextInt(10, 550);
        }
        bigShip.setLocation(x, y);
        add(bigShip);
    }
}

Как видите, я поместил цикл while внутри цикла for, но это не помогает.


person Tsiskreli    schedule 31.12.2013    source источник
comment
Что ж, самый быстрый способ — проверить, не занято ли уже какое-либо место, которое будет занимать корабль...   -  person Tony Hopkinson    schedule 31.12.2013
comment
Цикл while гарантирует, что начало корабля не будет находиться в одной и той же точке, но не учитывает остальную часть корабля, отсюда и перекрытие. Не могли бы вы также опубликовать код своей функции добавления, так как это, вероятно, лучшее место для размещения кода, включая цикл while и генерацию случайных чисел.   -  person conor    schedule 31.12.2013


Ответы (3)


Прежде всего, я бы предложил вам разделить слой модели и слой представления.

Другими словами, вы можете определить класс BattleShip, этот класс будет содержать положение корабля, размер и другие свойства, а также может содержать метод для проверки, пересекается ли он с каким-либо другим кораблем.

Затем вы можете создавать экземпляры и добавлять их в коллекцию только в том случае, если экземпляр не пересекается ни с одним экземпляром, присутствующим в коллекции.

Затем вы можете отобразить их все на экране за один раз.

person user1455836    schedule 31.12.2013

Я бы создал массив и сохранил значения местоположения каждого корабля, когда вы вводите их на холст. Затем для следующего корабля, прежде чем разместить его, проверьте, занято ли уже это место на холсте. Очевидно, вы должны помнить, что корабли бывают разной длины, а некоторые из них горизонтальные и вертикальные.

person edwoollard    schedule 31.12.2013

Недавно я реализовал эту игру в рамках интервью. Мое решение состояло в том, чтобы просто разбить сетку случайным образом на N > 3 областей, а затем разместить 3 требуемых корабля (2 линкора и 1 эсминец), поместив один корабль в одну область. N областей не перекрываются попарно и вместе покрывают всю сетку (я думаю, это называется замощением сетки). Так как N областей не пересекаются, корабли тоже не пересекаются. Это решение очень понравилось интервьюерам. Кроме того, случайность также была гарантирована.

Альтернативное решение состояло в том, чтобы продолжать размещать корабли в случайных позициях и продолжать проверять, не пересекается ли корабль K с каким-либо из ранее размещенных кораблей (1,2,3,...,K-1), но это имело некоторые очевидные недостатки, которые я не учел. Мне нравится: 1) сама проверка перекрытия корабля, которая должна быть сделана, не очень элегантна и чиста; 2) тот факт, что это не детерминированная процедура, и вы не знаете заранее, завершится ли ваш алгоритм размещения, и если да, то через сколько шагов он завершится.

Поэтому я только что сделал это случайное решение для разбиения/плитки, упомянутое выше.

person peter.petrov    schedule 31.12.2013
comment
Я думаю, размещение кораблей в случайных позициях имеет больше смысла в игре. Было бы немного раздражающе играть в игру, если вы заранее знаете места кораблей. - person user1455836; 31.12.2013
comment
@user1455836 user1455836 Да, конечно, но случайность также гарантирована (поскольку разбиение/разбиение сетки является случайным, т. е. я не всегда использую одно и то же разбиение сетки). - person peter.petrov; 31.12.2013