Decisione di classe per la scheda di programmazione del gioco orientata agli oggetti

2

Sto scrivendo un gioco orientato agli oggetti per divertimento in cui i giocatori di due squadre combattono. Devo implementare la funzione di spostamento per i giocatori in un labirinto. Il labirinto dovrebbe avere informazioni sulla posizione con alcune caratteristiche come altezza o tipo (collina, acqua ecc.). Quindi per implementare la posizione ho due idee. Il primo è che ho bisogno di una classe Board in cui memorizzo le informazioni sulla posizione in questa classe e anche la classe Location che ha coordinate x e y. La classe del giocatore fa riferimento alla classe Board.

class Board{
public:
    std::vector<Location> map;
};

class Location{
public:
    int x_coordinate;
    int y_coordinate;
    int height;
    Feature ground_feature;
};

La seconda idea è che invece di avere una classe Board avrò una classe Location che ha coordinate x e y e una lista statica di tutte le coordinate nel gioco. Questa classe di località sarà membro della classe Player.

class Location{
public:
    int x_coordinate;
    int y_coordinate;
    int height;
    Feature ground_feature;
    static std::vector<Location> map;
};

Potresti dirmi quali di queste idee di implementazione sono più solide e verificabili e perché? O quale sarebbe l'idea migliore per implementare tale requisito.

    
posta overload_resolution 23.07.2018 - 07:00
fonte

4 risposte

2

La prima soluzione sembra molto più pulita. Il secondo conferisce a ciascun pezzo della conoscenza del bordo la scheda completa, che "sembra" sbagliata.

Molto meglio avere la bacheca che conosce tutti i pezzi su di essa includendo un riferimento a ciascun pezzo sulla scacchiera. Per fare ciò, aggiungi un riferimento al pezzo (se esiste) alla tua classe Location. I pezzi stessi quindi non hanno bisogno di sapere dove si trovano, il tabellone ne terrà traccia per loro.

    
risposta data 23.07.2018 - 07:36
fonte
0

So che potrebbe essere noioso, ma la prima cosa è entrare nella giusta mentalità. Nell'orientamento agli oggetti i dati sono di secondaria importanza. Le cose importanti sono:

  1. Quale funzionalità (aziendale) desidero supportare?
  2. Quale conoscenza (non i dati!) devo avere, e come li localizzo, quindi esattamente una cosa possiede un dato dato di conoscenza?

Quindi, poiché esiste solo una singola funzionalità che conosciamo, ovviamente è necessaria solo una classe. Chiamiamo questo Board . Il Board sa dove sono le cose, così come il terreno, e ha un unico metodo pubblico chiamato move .

Lo so, probabilmente stai dicendo, che non supporterebbe i miei altri casi d'uso. Probabilmente è giusto. Il design deve cambiare con ogni nuovo caso d'uso. Il più grande errore di solito nella progettazione orientata agli oggetti è cercare di rendere le cose generiche, pensando di supportare qualsiasi caso d'uso in futuro. Questo di solito viene fatto semplicemente pubblicando i suoi dati, il che è un grosso errore.

Quindi non pubblicare dati, pubblicare (business!) funzionalità e considerare tutti i casi d'uso (attualmente noti) durante la progettazione, non di più, non di meno.

    
risposta data 23.07.2018 - 11:23
fonte
0

Questo è solo, probabilmente, off the wall, ma ultimamente ho fatto troppe cose nel codice RDBMS. Perché non più lezioni. In particolare, rendi la Location Feature indipendente e Location un concetto di prima classe da solo (nessuna informazione sulle caratteristiche):

// Prefer Immutable
class Feature {
  public:
   // Stuff
};

// Prefer Immutable
class Location{
  public:
    int x_coordinate;
    int y_coordinate;
    int height;
};

class PlayingArea{ // Board
  public:
    std::vector<Location> map;
};

// Immutable? 
class FeatureLocation { 
   public:
      Location location; // should be const
      Feature ground_feature; // Design decision: can change or make 
                              // immutable and replace with new
                              // FeatureLocation that has same Location
                              // or maybe make location a Decorator 
                              // (composable features) 
};

class Features{
  public:
    std::vector<FeatureLocation> map;
};

Questo suddivide i dati in modo diverso, ma sembra che gestirà i dati in blocchi più coerenti, e possibilmente più suscettibile di suddividere le regole aziendali relative alla configurazione del gioco, all'esecuzione e, (se si utilizza qualche algos di computer) valutazione. / p>

La master class (Game? Scenario? Instance?) dovrebbe creare e gestire Features, Board e FeaturesLocation, ma l'altra è più adatta all'inizializzazione statica O ai plugin dinamici.

Ad ogni modo, non conoscendo più le regole del gioco e il motore, è così che comincerei.

    
risposta data 23.07.2018 - 13:10
fonte
0

Prima di tutto ...

Le due opzioni che hai non sono necessariamente mutuamente esclusive. Ad esempio, potresti rendere Location un tipo di valore immutabile generato dal tuo Board . Board decide ancora la posizione (opzione 1), ma una Location può essere passata o memorizzata come valore (opzione 2).

La cosa importante da considerare qui è che esiste solo una vera fonte di informazioni (il Board ). Se Board è colui che crea tutto Locations , Board non dovrebbe mai aggiustarsi in base a a Location che riceve (perché ciò crea una fonte di potenziale disinformazione). La conoscenza di Board è considerata corretta. Altre fonti contengono un valore ugualmente corretto o sono considerate errate (e in entrambi i casi, dovresti utilizzare il valore di Board ).

Tuttavia ...

Se scegli una sola opzione, l'opzione 1 è la più pulita.

L'opzione 2 funziona solo se le classi tutte che utilizzano posizioni e comunicano tra loro si trovano nella stessa pagina. Questo viola DRY (più classi hanno lo stesso% di gestione diLocation), è soggetto a errori (cosa succede se una classe lo gestisce in modo diverso?), E non intuitivo (una posizione è un nome abbreviato per una "posizione della scheda", una posizione è priva di significato se non è nell'ambito di una scheda).

Prendendo ispirazione dall'architettura server-client, l'interazione della classe Player con la bacheca dovrebbe consistere nelle azioni che un giocatore può prendere ( MoveUp , MoveDown , MoveLeft , MoveRight ). Il consiglio quindi traduce quell'azione in un cambiamento di movimento.

Questo garantisce che il tuo giocatore non abbia bisogno di logica di controllo delle tessere. Ad esempio, diciamo che se la tessera successiva è di ghiaccio, il giocatore quindi lo attraversa e ha spostato 2 tessere anche se intendevano spostare solo 1 tessera.
Non vuoi che la Commissione faccia ciecamente il giocatore facendo la mossa giusta; cosa succede se il giocatore non è a conoscenza dello stato della scacchiera? (ad esempio, le lastre di ghiaccio si sono formate solo di recente)?

    
risposta data 23.07.2018 - 13:28
fonte

Leggi altre domande sui tag