Я разрабатываю настольную игру под названием Санторини, используя Java, и у меня возникают некоторые трудности с определением правильного способа / шаблона для реализации его c polymorphi.
Для те, которые не знают правил, я вкратце изложу их часть: базовый ход c состоит из фазы перемещения, когда вы перемещаете своего «персонажа», за которым следует фаза сборки, в которой вы строите блок на доске. В расширенной версии игры каждый игрок выбирает карту Бога в начале игры, и эта карта дает игроку особые способности, которые радикально изменяют его ход, как в порядке его действий, так и в их модификациях. Например, карта Бога может изменить порядок, в котором вы выполняете эти действия, давая вам дополнительное движение или действие по наращиванию (например, вы можете построить до и после перемещения), или изменить возможные места, доступные для действия (например, вы можете переместите своего персонажа в места, которые уже заняты другими противниками, что обычно вы не можете). Поэтому я изменил игровую логику c, сделав ее четырехфазным поворотом (движение, сборка, дополнительное перемещение, дополнительное построение).
Проблема, с которой я столкнулся, заключается в том, что, следуя типичному дизайну MVC Я хочу иметь только один Контроллер, который имеет дело со всеми доступными Богами, но я не уверен, как этого достичь. Моей первой идеей было создание абстрактного класса с именем God с ArrayList availableActions и абстрактных методов, таких как getAvailableMove () , getAvailableBuild () , которые возвращали бы список пространств, доступных пользователю для данного конкретного действия. Затем существует класс для каждого Бога, который расширяет абстрактный класс Бога и переопределяет методы, а также добавляет дополнительные методы для дополнительных фаз. Каждый Бог будет создавать список availableActions в своем конструкторе после логина своего хода c, так что контролеру просто нужно go через каждое действие в ArrayList, чтобы "воспроизвести" ход.
public abstract class God {
protected ArrayList<Phase> availableActions= new ArrayList<>();
protected GodsNames name;
public abstract ArrayList<Space> getAvailableMove(Player player);
public abstract ArrayList<Space> getAvailableBuild(Player player);}
public class Artemis extends God {
Artemis(){
this.name = GodsNames.ARTEMIS;
availableSteps.add(Phase.MOVE);
availableSteps.add(Phase.BUILD);
availableSteps.add(Phase.OPTIONALMOVE);
}
@Override
public ArrayList<Space> getAvailableMove(Player player) {...}
@Override
public ArrayList<Space> getAvailableBuild(Player player) {...}
public ArrayList<Space> getAvailableOptionalMove(Player player) {...}
}
Проблема в том, что многие Боги совместно используют стандартную реализацию getAvailableMove или getAvailableBuild. Но я не могу написать реализацию по умолчанию для обоих методов класса God, конечно, если бы класс не был абстрактным. И поскольку в игре не существует объекта «generi c God», я думаю, что было бы бессмысленно делать «God» неабстрактным классом. Но, делая это, я пишу грузы для дополнительного кода даром (богов больше 30). Есть ли другой шаблон дизайна, который мог бы больше соответствовать динамике этой настольной игры? Кто-нибудь из вас сталкивался с подобной ситуацией в плане реализации игровой логики c? Я знаю, что объяснение игры не может быть сделано точно в нескольких словах, но я старался быть максимально ясным. Спасибо всем, кто ответит или просто прочитает вопрос.