Вопрос

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

У меня есть Игра класс, представляющий пошаговую настольную игру, мы можем предположить, что для целей этого вопроса он похож на Monopoly.В моем дизайне у меня есть Игрок класс, содержащий метод Поворот.

Тот Самый Игра циклы проходят через все Игрокs и вызывает метод takeTurn, чтобы выполнить все необходимые действия для завершения поворота.Я хочу иметь возможность иметь n игроков и иметь возможность установить произвольное количество из них компьютерными игроками.Итак, моя мысль состояла в том, чтобы создать класс HumanPlayer и Компьютерный игрок класс, оба из которых являются производными от Player.

Тот Самый Игра знает только то, что Игрок класс и просто вызывает Поворот метод для каждого Игрок по очереди.Моя проблема заключается в том, что Компьютерный игрок объекты могут быть полностью автоматизированы, т.е.придерживаясь примера с монополией, вы можете принять решение о покупке недвижимости, используя некоторую логику.Теперь, с учетом Человек - игрок объект, ему необходимо получить входные данные от фактического пользователя, чтобы иметь возможность купить свойство, например, что, по-видимому, подразумевает другой интерфейс и потенциально означает, что они не должны выводиться

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

Будем признательны за любые мнения по этому поводу.

Это было полезно?

Решение

Я думаю, вам не следует позволять Игровому классу обрабатывать ввод-вывод.таким образом, (блокирующий) метод takeTurn скроет с игрового поля средства реализации.он может использовать другие объекты для связи с пользователем.

Все, о чем должен заботиться класс игры, - это состояние доски и ход.все игроки должны реализовать однопользовательский интерфейс и скрыть всю реализацию от Игры.

Другие советы

Если игра управляет игровым состоянием и выполняя ввод-вывод, Игра делает слишком много.

Вы хотите, чтобы Игра была строго сфокусирована только на правилах, поворотах и изменениях состояния.Игра не знает, что такое игрок;он знает только то, что у него есть игроки.

Вы хотите, чтобы игроки изучали состояние Игры и выполняли разрешенные действия во время своих ходов.

Игроки-люди и Игра в целом и то , и другое используйте общий пакет ввода-вывода, который показывает состояние игры и запрашивает у пользователей их ввод.

Вы можете эффективно использовать Java Observable сделав пакет ввода-вывода Observer из Игры.Таким образом, изменения состояния игры передаются в систему ввода-вывода для отображения, ведения журнала или и того, и другого.

У меня, вероятно, не было бы двух HumanPlayer и ComputerPlayer классы, но один-единственный Player класс, который настраивается во время создания с соответствующей стратегией ввода.

Способ, которым игрок получает информацию для принятия решения о своем ходе в следующий ход игры, является Только вещь, которая отличается (по крайней мере, от исходного описания проблемы), поэтому просто инкапсулируйте это в отдельную абстракцию.

Какой бы высокоуровневый класс ни создавал игру, он также должен создать два набора игроков (один человек, другой компьютерно смоделированный) с соответствующей стратегией ввода для каждого, а затем просто передать эти объекты игрока игровому объекту.Тогда Игровой класс будет вызывать только TakeTurn метод в заданном списке игроков, для каждого нового хода.

Вместо того, чтобы сообщать игровому классу, что существует только один человек, почему бы не позволить ему получать этот ввод во время меню / инициализации игры?Если игроков больше, это можно решить с помощью какой-либо формы ввода (выберите игроков в меню) до инициализации игрового класса.

Интерфейс, который Игрок подарки для Игра ортогональна поведению производных Игрок классы.

Тот факт, что реализация Поворот варьируется в зависимости от конкретного типа устройства. Игрок объект не должен быть причиной для беспокойства.

Я думаю, что Game Класс не должен касаться каких-либо реализаций классов Player, а также игнорировать Пользовательский интерфейс.

Любой пользовательский ввод должен обрабатываться HumanPlayer класс.

Я бы сказал, что Игра классу должно быть все равно, компьютерный это игрок или человек.Он всегда должен вызывать Поворот о следующем классе игроков.Если это игрок-человек, то ответственность за это лежит на Игрок класс, позволяющий общаться с пользователем и спрашивать его, что делать.Это означает, что он будет блокироваться до тех пор, пока пользователь не примет решение.Поскольку обычно взаимодействие с пользовательским интерфейсом происходит в главном потоке приложения, важно только, чтобы блокировка Поворот не блокирует приложение в целом, в противном случае ввод данных пользователем не может быть обработан во время Игра ждет Поворот.

Вместо того, чтобы Игра вызов класса Поворот на всех игроках игроки должны сделать колл Поворот на Игра класс и Игра класс должен проверить, правильный ли игрок делает свой ход.

Это должно помочь решить проблему Пользователь и Компьютер проблема с игроком.

Я не уверен, что это то, чего вы хотите

public abstract class Player 
{
  int position;
  DecisionMaker decisionDependency;

  ...

  public void TakeTurn()
  {
    position += RollDice();
    GameOption option GetOptions(position);
    MakeDescion(option);
  }

  protected int RollDice()
  {
    //do something to get the movement
  }

  protected abstract void MakeDecision(GameOption option);

}

Public class ComputerPlayer : Player
{
  public ComputerPlayer()
  {
    decisionDependency = new AIDecisionMaker();
  }

  protected override void void MakeDecision(GameOption option)
  {
    decisionDependency.MakeDecision(option);
    //do stuff, probably delgate toan AI based dependency
  }
}

Public class HumanPlayer : Player
{
  public HumanPlayer()
  {
    decisionDependency = new UIDecisionMaker();
  }

  protected override void void MakeDecision(GameOption option)
  {
    decisionDependency.MakeDecision(option);
    //do stuff, probably interacting with the a UI or delgate to a dependency
  }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top