Не расстраивайтесь из-за того, что не поняли рекурсию в результате чтения этого документа.Это не очень хорошо объясняет рекурсию.(Это сложная концепция - я, вероятно, тоже не справлюсь).В конечном счете, вам нужно попытаться заставить вашу программу делать то, что вы делаете.Я попытаюсь объяснить это с этой точки зрения.
Рекурсия полезна, потому что она позволяет нам (один раз) кодировать шаг в решении, а затем повторить этот шаг, используя в качестве входных данных результаты, которыебыли просто рассчитаны.Попытайтесь взглянуть на свою проблему с вашей точки зрения, а не на какой-нибудь произвольный алгоритм.Возможно, вы слишком усердно пытаетесь понять алгоритм из бумаги.
Попробуйте подумать так: В начале игры игрок 1 делает игру.Ваша программа должна выбрать ход для Игрока 2. Но игрок 2 должен подумать об остальной части игры (ДЛЯ КАЖДОГО ВОЗМОЖНОГО ДВИЖЕНИЯ).
- Игрок 2 может выбрать один из 8 возможных ходов.
- Игрок 1 может выбирать из 7
- Игрок 2 может выбирать из 6
- Игрок 1 может выбирать из 5
- Игрок 2 может выбирать из 4
- Игрок 1 может выбрать из 3
- Игрок 2 может выбрать из 2
- Игрок 1 занимает последний квадрат.
Вы можете переформулировать этов:
текущий игрок равен 2, присваивает вес всем возможным оставшимся вариантам для текущего игрока .
текущий игрок равен 1, присваивает вес всем возможным оставшимся вариантам длятекущий игрок .
текущий игрок 2, присваивает вес всем возможным оставшимся вариантам для текущего игрока .
текущий игрок равен 1, присваивает вес всем возможнымоставшиеся варианты для текущего игрока .
текущий игрок равен 2, присваивает вес всем возможным оставшимся вариантам для текущего игрока .
текущий игрок равен 1, даютвес всех возможных оставшихся вариантов для текущего игрока .
curарендный игрок равен 2, присваивает вес всем возможным оставшимся вариантам для текущего игрока .
текущий игрок равен 1, присваивает вес всем возможным оставшимся вариантам для текущего игрока ,
Вы можете перефразировать это следующим образом: данный игрок, переключатель игрока и дают вес всем возможным вариантам для текущего игрока .
Повторяйте до тех пор, пока больше не будет выбора
Вы можете перефразировать это следующим образом: данный игрок, игрок переключения и CheckGoodness () повторяются до тех пор, пока больше не будет возможности выбора
Итак, вернемся к вашей записи.Автор использует игроков 1 & -1.Зачем?Потому что, когда вы проходите движения глубже и глубже, вы должны поменять местами игроков, и очень легко переключать игроков, когда вы спускаетесь по уровням, подобным этому (я говорю только об игроке здесь:
public int CheckGoodness(bool playerID)
{
playerID = -playerID;
if (!endConditionMet)
{
goodness = CheckGoodness(playerID);
}
return goodness;
}
Наряду сигрок, вы должны передать что-то, что представляет состояние всех возможных оставшихся ходов. Проблема в том, что если вы передадите что-то, что проходит в качестве ссылки, любое внесенное вами изменение будет отражено в ваших исходных данных. Убедитесь, что это не такВероятно, именно поэтому @CodeInChaos предложил вам клонировать.
Обратите внимание, что в рекурсии вы должны убедиться, что у вас ВСЕГДА есть способ завершить последовательность вызовов. Вы должны изменить то, на что полагается ваше конечное условие.В этом случае количество возможных ходов уменьшается. В противном случае вы звоните навсегда и исчерпываете память.
РЕДАКТИРОВАТЬ: Добавлено объяснение класса доски.
Подумайте об этом из общей картины. Aкласс представляет собой представление о реальной вещи (например, объект). У вещи есть атрибуты, которые описываютт.Это данные класса.Вещи также делают действия.Это методы.Еще одно определение класса, которое я слышал, - это данные и операции над этими данными.
Подумайте, какие объекты есть в игре.2 игрока и доска.Не намного больше.
Игрок может двигаться и имеет уникальный идентификатор (в данном случае «X» или «O») и может быть человеком или ИИ. Я не могу думать ни о чем другом (это имеет значение) в данный момент, но обычно есть больше вещей, которые могут быть там, но на самом деле не влияют на программу (например, цвет глаз). Это также, где вы могли бы использовать наследование. У вас есть класс игрока с абстрактным методом перемещения. Человеческий класс, который наследует от игрока с помощью метода переопределения перемещения, который принимает входные данные из пользовательского интерфейса, компьютерный / AI-класс, который наследует от игрока и переопределяет метод перемещения, вычисляя ход с рейтингом добродетели.
На плате есть данные:
- сетка возможных игровых локаций 3 на 3 (кстати, это МОЖЕТ быть также коллекция объектов локаций)
- может потребоваться представление для игроков 1 и 2
Действия доски МОГУТ быть:
- принимает ход игрока (человека или ИИ), записывает его, если он действителен, определяет выигрыш и возвращает показатель хорошего хода, плохого хода, окончания игры или победы
- Может быть способ вернуть победителя текущей игры
- Вероятно, нужен метод сброса
- Может иметь историю ходов
У вас может быть статический класс GoodNess (может потребоваться более подходящее имя)
без данных, но с одним методом (или это может быть другой метод класса класса:
- принять доску, вычислить и вернуть массив добродетелей или просто вернуть лучший ход
ИИ может вызвать метод Goodness GetBestMove перед тем, как сделать ход.
Рекурсия будет изолирована от этого метода GetBestMove.
Обратите внимание, что ни один из них не установлен в камне. Классы определяются тем, что, по вашему мнению, должно быть в нем. Все зависит от того, как вы считаете, будет лучшим способом решения проблемы. Если у вас все еще есть проблемы, обновите ваш вопрос кодом, который вы пытались заставить работать. Это действительно помогает рисовать диаграммы, когда вы начинаете выкладывать свой код.
Удачи, надеюсь, это поможет, и я постараюсь улучшить мониторинг уведомлений StackOverflow.