Указатель стека при рекурсии

236
13 апреля 2019, 22:30

Прошу объяснить, как работает указатель стека при рекурсивном вызове метода из самого себя. Пишу морской на Java. В классе "Корабль" есть метод, который задает кораблю случайные координаты (X и Y). В этом методы стоит проверка, не зайдет ли корабль с этими координатами за границы поля, и если зайдет, то метод метод вызывает сам себя.

if (orientation == Orientation.VERTICAL) {
        if (y > GameMap.HEIGTH - body.length) {
            if (resetCount == 10) {
                resetCount = 0;
                orientation = Orientation.HORIZONTAL;
                orientationLock = true;
            }
            resetCount++;
            this.resetCoordinates();
            this.setRandomCoordinates();
        }
        for (int i = 0; i < body.length; i++) {
            body[i].setY(y++);
            body[i].setX(x);
        }

Была проблема, что после срабатывания этой проверки корабль, при успешном прохождении новой проверки, корректно отрабатывал присвоение координат, но после этого снова начинал их задавать, причем со старыми значениями (до входа в рекурсию) X и Y.

Бился несколько часов, прежде чем понял, что надо было изменить код таким образом, то есть добавить ветвление после IF:

else {
    for (int i = 0; i < body.length; i++) {
        body[i].setY(y++);
        body[i].setX(x);
    }
}

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

Правильно ли я понял, что рекурсия - как клубок, возвращается до места, откуда была вызвана, и продолжает выполнение с точки вызова, запоминая состояние?

Весь код метода после исправления:

public void setRandomCoordinates() {
    Random rand = new Random();
    int setOrientation = rand.nextInt(2);
    if (!orientationLock) {
        orientation = setOrientation == 0 ? Orientation.HORIZONTAL : Orientation.VERTICAL;
    }
    int x = rand.nextInt(10);
    int y = rand.nextInt(10);
    if (orientation == Orientation.VERTICAL) {
        if (y > GameMap.HEIGTH - body.length) {
            if (resetCount == 10) {
                resetCount = 0;
                orientation = Orientation.HORIZONTAL;
                orientationLock = true;
            }
            resetCount++;
            this.resetCoordinates();
            this.setRandomCoordinates();
        } else {
            for (int i = 0; i < body.length; i++) {
                body[i].setY(y++);
                body[i].setX(x);
            }
        }
    } else if (orientation == Orientation.HORIZONTAL) {
        if (x > GameMap.WIDTH - body.length) {
            if (resetCount == 10) {
                resetCount = 0;
                orientation = Orientation.VERTICAL;
                orientationLock = true;
            }
            resetCount++;
            this.resetCoordinates();
            this.setRandomCoordinates();
        } else {
            for (int i = 0; i < body.length; i++) {
                body[i].setY(y);
                body[i].setX(x++);
            }
        }
    }
}
READ ALSO
JavaFx прижать блоки к верху и к низу окна

JavaFx прижать блоки к верху и к низу окна

Мне нужно сделать, чтобы у меня три label были вверху окна (друг за другом) в полную ширину, один внизу окна, а в центре находилась формаМожет...

154
Печать слов, в предложении, с заглавной буквы [закрыт]

Печать слов, в предложении, с заглавной буквы [закрыт]

Объясните пожалуйста как работает код

172
Помогите с оформлением по MVC кода на джаве

Помогите с оформлением по MVC кода на джаве

Не могу разобраться с mvcПомогите пожалуста

158
IE не понимает метод forEach

IE не понимает метод forEach

Использую маленький скрипт

169