Domanda

ho scritto un parser di file per un gioco che sto scrivendo per rendere più facile per me di cambiare vari aspetti del gioco (cose come i dati di carattere / stadio / collisione). Per esempio, potrei avere una classe di caratteri in questo modo:

class Character
{
public:
    int x, y; // Character's location
    Character* teammate;
}

Ho impostato il mio parser per leggere da un file la struttura di dati con una sintassi simile al C ++

Character Sidekick
{
    X = 12
    Y = 0
}

Character AwesomeDude
{
    X = 10
    Y = 50
    Teammate = Sidekick
}

Questo creerà due strutture di dati e metterli in una map<std::string, Character*>, in cui la stringa chiave è qualunque sia il nome che ho dato (in questo caso Sidekick e AwesomeDude). Quando il mio parser vede un puntatore a una classe, come il puntatore compagno di squadra, è abbastanza intelligente per cercare nella mappa per andare a prendere il puntatore a quella struttura di dati. Il problema è che non riesco a dichiarare compagno di squadra di Sidekick per essere AwesomeDude perché non è stato messo nella Mappa Atmosfera ancora.

Sto cercando di trovare il modo migliore per risolvere questo in modo che io possa avere le mie strutture dati oggetti di riferimento che non sono ancora stati aggiunti alla mappa. Le due soluzioni più semplici che mi viene in mente sono (a) aggiungere la possibilità di inoltrare dichiarare strutture di dati o (b) hanno il parser leggere il file due volte, una volta per popolare la mappa con puntatori a strutture di dati vuoti e una seconda volta per passare attraverso e riempirli a.

Il problema di (a) è che anche io posso decidere quale costruttore di chiamare su una classe, e se io ora dichiaro qualcosa avrei dovuto avere il costruttore sia a parte il resto dei dati, che possono essere fonte di confusione . Il problema con (b) è che potrei voler dichiarare Sidekick e AwesomeDude nelle proprie file. Avrei dovuto fare il mio parser in grado di prendere un elenco di file da leggere piuttosto che solo uno alla volta (questo non è poi così male immagino, anche se a volte mi potrebbe desiderare di ottenere un elenco di file di leggere da un file). (B) ha anche l'inconveniente di non essere in grado di utilizzare le strutture di dati dichiarati in seguito nel costruttore stesso, ma non credo che sia un affare enorme.

Da che parte suona come un approccio migliore? C'è una terza opzione che non ho pensato? Sembra che ci dovrebbe essere una soluzione intelligente per questo con riferimenti puntatore o vincolante o qualcosa del genere ...: - / Suppongo che questo sia un po 'soggettiva in base a quali caratteristiche che voglio dare a me stesso, ma qualsiasi input è il benvenuto.

È stato utile?

Soluzione

Quando si incontra il riferimento per la prima volta, semplicemente conservarlo come riferimento. Quindi, si può mettere il personaggio, o il riferimento, o qualsiasi altra cosa in un elenco di "riferimenti che devono essere risolti in seguito".

Quando il file è fatto, correre attraverso quelle che hanno riferimenti e li risolve.

Altri suggerimenti

Bene, lei ha chiesto una terza opzione. Non è necessario utilizzare XML, ma se si segue la seguente struttura, sarebbe molto semplice da usare un parser SAX per costruire la vostra struttura di dati.

In ogni caso, invece di fare riferimento a un compagno di squadra, ogni personaggio fa riferimento a un team (squadra blu in questo caso). Ciò disaccoppiare il problema di riferimento circolare. Basta fare in modo di avere una lista delle squadre prima dei caratteri.

<team>Blue</team>

<character>
    <name>Sidekick</name>
    <X>12</X>
    <Y>0</Y>
    <teamref>Blue</teamref>
</character>

<character>
    <name>Sidekick</name>
    <X>10</X>
    <Y>50</Y>
    <teamref>Blue</teamref>
</character>

Personalmente, mi piacerebbe andare con b). Dividere il codice in classi Parser e Validator, entrambi operanti sulla stessa struttura di dati. Il parser leggerà e analizzare un file, riempiendo la struttura dei dati e la memorizzazione di tutti i riferimenti agli oggetti come i loro nomi testuali, lasciando il vero puntatore nullo nella struttura, per ora.

Una volta terminato il caricamento dei file, utilizzare la classe Validator per convalidare e risolvere eventuali riferimenti, riempiendo i puntatori "reali". Si vuole riflettere su come strutturare i dati per rendere queste ricerche piacevole e veloce.

Will ha detto esattamente quello che stavo per scrivere. Basta tenere una lista o qualcosa con i riferimenti non risolti.

E non dimenticare di gettare un errore se ci sono riferimenti non risolti una volta finito di leggere il file = P

Invece di memorizzare oggetti carattere nella mappa, memorizzare un proxy per il personaggio. Il proxy che contengono un puntatore all'oggetto carattere effettivo quando l'oggetto viene caricato. Il tipo di carattere :: compagno di squadra sarà cambiato a questo tipo di proxy. Quando si legge in un riferimento che non è già nella mappa, si crea un proxy e utilizzare il proxy. Quando si carica un carattere che si dispone già di un proxy vuoto nella mappa, popolarlo con il tuo personaggio appena caricata. Si consiglia inoltre di aggiungere un contatore per tenere traccia del numero di delega vuota si ha nella mappa in modo da sapere quando tutti i personaggi di riferimento sono stati caricati.

Un altro livello di riferimento indiretto .... è sempre facilitare la programmazione e più lento.

Una possibilità sarebbe quella di invertire l'obbligo. Il Map è responsabile per il riempimento nel riferimento

template<T> class SymbolMap // I never could rememeber C++ template syntax
{
   ...

   /// fill in target with thing name
   /// if no name yet, add it to the list of thing that will be name
   void Set(T& target, std::string name);

   /// define name as target
   /// go back and fill in anything that needs to be name
   void Define(T target, std::string name);

   /// make sure everything is resolved
   ~SymbolMap()
}

che non interagiscono bene con valore / semantica in movimento, ma ho il sospetto che non vi saranno grandi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top