Pergunta

Eu estive pensando sobre isso orientada a objeto pergunta projeto por um tempo agora e ter incapaz de chegar a uma solução satisfatória, por isso pensei que eu ia jogá-lo abrir às multidões aqui para algumas opiniões.

Eu tenho um Jogo classe que representa um jogo de tabuleiro baseado em turnos, podemos supor que é semelhante ao monopólio para os fins da presente questão. Na minha concepção Eu tenho um Jogador classe que contém um método TakeTurn .

O Jogo percorre todos Jogador S e chama o método TakeTurn para fazer todas as coisas necessárias para completar a sua vez. Eu quero ser capaz de ter n número de jogadores, e ser capaz de definir um número arbitrário de que eles sejam jogadores de computador. Então, meu pensamento era ter uma classe HumanPlayer e um ComputerPlayer classe, sendo que ambos derivam Player.

O Jogo só conhece o Jogador classe e simplesmente chama o TakeTurn método em cada Jogador , por sua vez. Meu problema vem no fato de que ComputerPlayer objetos pode ser completamente automatizado, mantendo ou seja, com o exemplo Monopoly, pode decidir comprar uma propriedade usando alguma peça de lógica. Agora, com o HumanPlayer objeto, ele precisa obter uma entrada do usuário real para ser capaz de comprar um imóvel, por exemplo, o que parece implicar uma interface diferente e potencialmente significa que eles devem não derive

Eu não tenho sido capaz de chegar a uma boa solução para o problema sem ter o Jogo class conhecer as implementações reais dos diferentes Jogador aulas explicitamente. Eu sempre poderia fazer a suposição no Jogo classe que não só nunca será jogadores humanos e computadores e efetivamente fechá-lo para a extensão, mas não parece ser uma boa programação OO.

Todas as opiniões sobre este seria apreciada.

Foi útil?

Solução

Eu acho que você não deve deixar a alça classe Jogo IO. Deste modo, o (bloqueio) TakeTurn método irá esconder do tabuleiro dos meios de aplicação. ele pode usar outros objetos para se comunicar com o usuário.

Toda a classe jogo deve preocupar-se com é o estado da placa e no turn. os jogadores devem todos implementar uma interface única Player, e esconder toda a execução do jogo.

Outras dicas

Se o jogo está a gerir o estado do jogo e fazendo I / O, o jogo está fazendo muito.

Você quer jogo a ser fortemente centrada em regras e voltas apenas e mudanças de estado. O jogo não sabe o que um jogador é; ele só sabe que tem jogadores.

Você quer jogadores para examinar o estado do jogo e executar as ações legais durante os seus turnos.

jogadores humanos eo jogo como um todo ambos compartilhar um pacote comum I / O que estado game shows e pede seres humanos para a sua entrada.

Você pode fazer bom uso do Observable Java, tornando o I / O pacote um Observer do Jogo. Dessa forma, as mudanças de estado do jogo são relatados para o I / O para exibição ou exploração madeireira ou ambos.

Eu provavelmente não tem duas classes HumanPlayer e ComputerPlayer, mas uma única classe Player que é configurado no momento da criação com a estratégia de entrada adequada.

A forma como a informação o jogador obtém para decidir seu movimento no próximo turno do jogo é a única coisa que varia (a partir da descrição do problema original, pelo menos), então apenas encapsular que em um abstração separada.

Whatever classe de alto nível que configura o jogo também deve criar os dois conjuntos de jogadores (um humano, um outro simulado por computador), com a estratégia de entrada adequada para cada um, e depois simplesmente dar a estes jogadores objetos ao objeto jogo . A classe jogo vai só então chamar o método TakeTurn na lista dada de jogadores, para cada novo turno.

Em vez de dizer a classe jogo há sempre apenas uma humana, por que não deixá-lo chegar que a entrada durante o menu / inicialização do jogo? Se houver mais jogadores, que podem ser decididas através de alguma forma de entrada (seleccionar jogadores no menu), antes da inicialização da classe jogo.

A interface que Jogador apresenta a Jogo é ortogonal ao comportamento dos derivados Jogador classes.

O fato de que a implementação de TakeTurn varia dependendo do tipo de concreto do Jogador objeto não deve ser um motivo de preocupação.

Eu acho que o Game Classe não deve preocupação com qualquer implementações das classes do jogador, e também ignorar o User Interface.

Todas as necessidades de entrada do usuário para ser tratado pela classe HumanPlayer.

Eu diria que, a Jogo classe deve se importa se este é um jogador do computador ou um jogador humano. Ele deve sempre chamar TakeTurn na próxima aula jogador. Se este é um jogador humano, é da responsabilidade do Jogador classe, para se comunicar com o usuário e pedir ao usuário o que fazer. Isso significa que ele irá bloquear até que o usuário fez a sua mente. Como a interação geralmente UI tem lugar no segmento principal de uma aplicação, é apenas importante que um bloqueio TakeTurn não vai bloquear o aplicativo como uma entrada inteira, caso contrário, o usuário não pode ser processado enquanto Jogo aguarda TakeTurn .

Em vez do Jogo classe chamando TakeTurn em todos os jogadores os jogadores devem chamar TakeTurn na Jogo classe e o Jogo classe deve validar se o jogador certo é tomar a sua vez.

Isso deve ajudar a resolver o usuário e Leitor problema do computador.

Im não tenho certeza se é isso que você quer

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
  }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top