Architettura del gioco e strategia di progettazione per un gioco di carte multiplayer
-
03-07-2019 - |
Domanda
Sono relativamente nuovo allo sviluppo del gioco, quindi ho deciso di creare un progetto hobby da zero sia per l'esperienza che per l'intrattenimento. Il gioco specifico è simile al poker noto come Three Card Brag . Il gioco si gioca nel film Lock, Stock and Two Smoking Barrels .
Ho letto alcuni degli argomenti su SO relativi allo sviluppo del gioco, anche se principalmente questa domanda . Ciò ha contribuito a rinnovare il modo originale in cui stavo creando gli oggetti.
Un problema particolare che sto riscontrando è la definizione dello stato del gioco. Il mio approccio iniziale era quello di separare tutto (ad esempio mantenendo stack di chip all'interno di una classe Player
) ma dopo aver letto le risposte alla domanda che ho citato in precedenza, sembra che tutti gli stati possibili del gioco debbano essere mantenuti all'interno di un oggetto GameState
. Quello che mi è venuto in mente è essenzialmente questo:
abstract class CardGameState
{
protected List<Player> _Players;
protected Player _CurrentPlayer;
protected Dictionary<Player, int> _Chips;
protected Dictionary<Player, Hand> _CurrentHand;
protected Dictionary<Player, PlayerStatuses> _PlayerStatus; // PlayerStatuses.InHand, PlayerStatuses.Folded, PlayerStatuses.SittingOut, etc.
/* etc. */
dove ogni CardGameState
è modificato da qualche azione:
public interface IAction
{
string Name { get; }
CardGameState Apply(CardGameState state);
bool IsLegal(CardGameState state);
}
Ora sento fortemente che ciò sta vanificando lo scopo della programmazione orientata agli oggetti, perché i dati specificamente correlati al giocatore (in questo caso, il suo stack di chip, la mano e lo stato corrente) non sono incapsulati dal Oggetto Player
.
D'altra parte, se un giocatore dovesse aumentare la scommessa, creerei un RaiseAction
che implementa IAction
, ma IAction
interface accetta solo lo stato di gioco attuale, che non credo sarebbe l'ideale se le pile di chip fossero archiviate nella classe Player
.
Fondamentalmente, la mia domanda è: posso avere il meglio dei due mondi in modo tale da poter avere una rappresentazione esatta dello stato del gioco mantenendo contemporaneamente tutti i dati relativi specificamente a un oggetto all'interno dello stato del gioco all'interno del suo oggetto dato?
Soluzione
Nei giochi online l'utilizzo del modello di comando (la tua IAction) è lo standard, e provato, il modo di farlo. Non è orientato agli oggetti nel senso del giocatore, ma le azioni sono orientate agli oggetti, quindi da un punto di vista puramente teorico è un solido modello di progettazione, immagino. E in pratica è così che ogni gioco online di successo che ho visto lo implementa, ma nota che i giochi di azione normalmente usano azioni / pacchetti discreti di dimensioni molto ridotte, fino a quando non diventa praticamente una sorta di flusso.
Modifica:
Molto tempo dopo aver risposto a questa domanda, sono tornato qui e ho capito che un'altra soluzione a questo problema è implementare i Giocatori, i Deck, ecc. di GameState come derivati ??da una classe IState con un < strong> Applica (azione IAction) . In questo modo gli oggetti applicano azioni su se stessi, invece di fare in modo che l'applicazione applichi azioni sugli oggetti, questo mapperebbe le azioni e dichiarerebbe un modello visitatore anziché un modello di comando. Entrambe le soluzioni funzioneranno, in cui il visitatore ha il sovraccarico maggiore e più incapsulamento, mentre il comando è la soluzione più semplice con meno incapsulamento.
Altri suggerimenti
Sembra che tu stia orientando l'Oggetto per il bene dell'Oriente ...
Sembra il classico problema di Bob Martin bowling .
EDIT: -Summary-
È una lettura lunga, ma fondamentalmente, attraverso TDD e refactoring, un'applicazione di bowling è passata da un enorme cluster con molte classi e polimorfismo a 20 o 30 eleganti linee di codice. Perché? Perché non avevano davvero bisogno di essere lì in primo luogo