Estou tentando ter uma ideia de como projetar e pensar de maneira orientada a objetos e gostaria de obter algum feedback da comunidade sobre este tópico. A seguir está um exemplo de um jogo de xadrez que desejo projetar de maneira OO. Este é um design muito amplo e meu foco neste estágio é apenas identificar quem é responsável por quais mensagens e como os objetos interagem entre si para simular o jogo. Indique se há elementos de design ruim (alto acoplamento, má coesão, etc.) e como melhorá-los.
O jogo de xadrez tem as seguintes classes
- Borda
- Jogador
- Peça
- Quadrado
- Jogo de xadrez
O tabuleiro é composto de quadrados e, portanto, o tabuleiro pode ser responsabilizado por criar e gerenciar objetos quadrados. Cada peça também está em um quadrado, então cada peça também tem uma referência ao quadrado em que está. (Isso faz sentido?). Cada peça então é responsável por se mover de uma casa para outra. A classe do jogador contém referências a todas as peças que possui e também é responsável por sua criação (o jogador deve criar peças?). Player tem um método takeTurn que, por sua vez, chama um método movePiece que pertence à classe da peça que muda a localização da peça de sua localização atual para outra localização. Agora estou confuso sobre o que exatamente a classe Board deve ser responsável. Presumi que fosse necessário determinar o estado atual do jogo e saber quando o jogo acabou. Mas quando uma peça muda ' s localização como o conselho deve ser atualizado? deve manter uma matriz separada de quadrados em que existem peças e que recebe atualizações conforme as peças se movem?
Além disso, ChessGame cria inicialmente o tabuleiro e os objetos do jogador que, por sua vez, criam quadrados e peças, respectivamente, e iniciam a simulação. Resumidamente, pode ser assim que o código no ChessGame se parece
Player p1 =new Player();
Player p2 = new Player();
Board b = new Board();
while(b.isGameOver())
{
p1.takeTurn(); // calls movePiece on the Piece object
p2.takeTurn();
}
Não estou certo de como o estado do conselho será atualizado. A peça deve ter uma referência ao tabuleiro? Onde deveria estar a responsabilidade? Quem detém quais referências? Por favor me ajude com suas entradas e aponte problemas neste projeto. Eu deliberadamente não estou focando em nenhum algoritmo ou detalhes adicionais do jogo, pois estou interessado apenas no aspecto do design. Espero que esta comunidade possa fornecer informações valiosas.
takeTurn()
se o movimento de p1 terminar o jogo. Comentário menos minucioso: Acho mais natural chamar os jogadoreswhite
eblack
.canMove()
função. E quando o movimento é concluído, todas as outras peças atualizam sua própria cópia interna do tabuleiro. Eu sei que não é o ideal, mas era interessante aprender C ++ naquela época. Mais tarde, um amigo não jogador de xadrez me disse que teriaclasses
para cada casa em vez de cada peça. E esse comentário me pareceu muito interessante.Respostas:
Na verdade, acabei de escrever uma implementação completa em C # de um tabuleiro de xadrez, peças, regras, etc. Aqui está mais ou menos como eu a modelei (a implementação real foi removida, pois não quero tirar toda a diversão de sua codificação):
A ideia básica é que o jogo / tabuleiro / etc simplesmente armazene o estado do jogo. Você pode manipulá-los para, por exemplo, definir uma posição, se for isso que você deseja. Eu tenho uma classe que implementa minha interface IGameRules que é responsável por:
Separar as regras das classes de jogo / tabuleiro também significa que você pode implementar variantes com relativa facilidade. Todos os métodos da interface de regras usam um
Game
objeto que eles podem inspecionar para determinar quais movimentos são válidos.Observe que eu não armazeno informações do jogador no
Game
. Tenho uma classe separadaTable
responsável por armazenar metadados do jogo, como quem estava jogando, quando o jogo aconteceu, etc.EDITAR: Observe que o objetivo desta resposta não é realmente fornecer a você um código de modelo que você possa preencher - meu código, na verdade, tem um pouco mais de informações armazenadas em cada item, mais métodos, etc. O objetivo é guiá-lo em direção ao objetivo que você está tentando alcançar.
fonte
Move
é uma classe para que você possa armazenar todo o histórico de movimentos em uma lista de movimentos, com notação e informações auxiliares, como a peça que foi capturada, a que posição um peão pode ter sido promovido, etc.Game
delegação a um implementadorIGameRules
ou você impõe regras fora do objeto? Este último parece inadequado, pois o jogo não pode proteger seu próprio estado, não?Aqui está minha ideia, para um jogo de xadrez bastante básico:
fonte
Recentemente criei um programa de xadrez em PHP ( site clique aqui , fonte clique aqui ) e o tornei orientado a objetos. Aqui estão as aulas que usei.
generate_legal_moves()
código aqui. Esse método recebe um tabuleiro, de quem é a vez, e algumas variáveis para definir o nível de detalhe da saída, e ele gera todos os movimentos legais para aquela posição. Ele retorna uma lista de ChessMoves.int
s.No momento, estou tentando transformar esse código em uma IA de xadrez, então ele precisa ser RÁPIDO.
generate_legal_moves()
Otimizei a função de 1500ms para 8ms e ainda estou trabalhando nisso. As lições que aprendi com isso são ...int
quando possível. É por isso queChessSquare
armazena rank and file comoint
, em vez de também armazenar um alfanuméricostring
com notação de quadrados de xadrez legível por humanos, como "a4".Eu sei que isso é antigo, mas espero que ajude alguém. Boa sorte!
fonte