Frage

Ich schrieb einen Datei-Parser für ein Spiel schreibe ich es einfach zu machen für sie verschiedene Aspekte des Spiels (Dinge wie die Zeichen / Bühne / Kollisionsdaten) zu ändern. Zum Beispiel könnte ich eine Zeichenklasse wie folgt aussehen:

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

ich meinen Parser up aus einer Datei zu lesen, in die Datenstruktur mit einer Syntax wie C ++

Character Sidekick
{
    X = 12
    Y = 0
}

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

Dies wird zwei Datenstrukturen erstellen und diese in einem map<std::string, Character*> setzen, wo der Schlüssel-String ist, was Name ich es gab (in diesem Fall Handlanger und AwesomeDude). Wenn mein Parser einen Zeiger auf eine Klasse sieht, wie der Mitspieler Zeiger, ist es klug genug, um in der Karte zu sehen, um den Zeiger auf die Datenstruktur zu holen. Das Problem ist, dass ich nicht Handlanger Teamkollegen erklärt AwesomeDude zu sein, weil sie noch nicht in die Zeichentabelle platziert wurde.

Ich versuche, den besten Weg zu finden, diese zu lösen, so dass ich meine Datenstrukturen Referenzobjekte haben, die noch nicht auf der Karte hinzugefügt. Die beiden einfachsten Lösungen, die ich denken kann, sind (a) fügen Sie die Möglichkeit, Datenstrukturen zu übermitteln erklären oder (b) haben der Parser durch die Datei zweimal gelesen, sobald die Karte mit Zeigern auf leeren Datenstrukturen zu füllen und ein zweites Mal durchlaufen und füllen sie sie aus.

Das Problem mit (a) ist, dass ich auch der Konstruktor entscheiden sich für eine Klasse zu rufen, und wenn ich mich etwas erklären würde ich den Konstruktor habe aus dem Rest der Daten auseinander, die verwirrend sein könnte . Das Problem mit (b) ist, dass ich Handlanger und AwesomeDude in ihren eigenen Dateien erklären möchte. Ich muss meine Parser in der Lage zu übernehmen, eine Liste von Dateien machen, anstatt nur einer nach dem anderen zu lesen (dies ist nicht so schlecht ist, ich denke, wenn auch manchmal könnte ich eine Liste von Dateien erhalten möchten, von einem lesen Datei). (B) hat auch den Nachteil, nicht Datenstrukturen in der Lage, später im Konstruktor deklarierten selbst zu verwenden, aber ich glaube nicht, das ist eine große Sache.

Welche Art und Weise klingt wie ein besserer Ansatz? Gibt es eine dritte Option Ich habe nicht gedacht? Es scheint, wie es sollte einige clevere Lösung dieses Problems mit Zeiger Referenzen oder Bindung oder etwas sein ...: - / Ich nehme an, das etwas subjektiv ist, basierend auf welche Funktionen ich mich geben wollen, aber jeder Eingang ist willkommen.

War es hilfreich?

Lösung

Wenn Sie die Referenz zum ersten Mal begegnen, einfach speichern Sie es als Referenz. Dann können Sie das Zeichen setzen, oder die Referenz, oder was auch immer auf einer Liste von „Referenzen, die später gelöst werden müssen“.

Wenn die Datei ausgeführt wird, durch diejenigen führen, die Verweise haben und sie lösen.

Andere Tipps

Nun, fragte sie eine dritte Option. Sie müssen nicht XML verwenden, aber wenn Sie die folgende Struktur folgen, wäre es sehr einfach, einen SAX-Parser zu verwenden, um Ihre Datenstruktur aufzubauen.

Auf jeden Fall statt einen Mitspieler zu referenzieren, jedes Zeichen verweist auf ein Team (blaues Team in diesem Fall). Dies wird die kreisförmige Referenz Problem entkoppeln. So stellen Sie sicher, die Teams Liste vor den Zeichen.

<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>

Persönlich würde ich mit b gehen). Splitting Ihren Code in Parser und Validator Klassen, die beide Betriebs auf der gleichen Datenstruktur. Der Parser liest und eine Datei analysieren, um die Datenstruktur füllen und alle Objektreferenzen als ihre lesenden Namen speichern, um jetzt die realen Zeiger null in Ihrer Struktur zu verlassen.

Wenn Sie fertig sind die Dateien geladen, die Validator-Klasse verwenden, um alle Verweise zu validieren und zu lösen, in den „echten“ Zeigern zu füllen. Sie wollen prüfen, wie die Daten zu strukturieren diese Lookups schön und schnell zu machen.

Will sagte genau das, was ich bin, darüber zu schreiben. Halten Sie einfach eine Liste oder etwas mit den ungelösten Referenzen.

Und vergessen Sie nicht, einen Fehler zu werfen, wenn es ungelöste Referenzen sind, sobald Sie die Datei gelesen haben = P

Stattdessen Character-Objekt in Ihrer Karte, speichert einen Proxy für Charakter zu speichern. Der Proxy enthält als einen Zeiger auf das eigentliche Charakterobjekt, wenn das Objekt geladen wird. Die Art der Charakter :: Mitspieler wird auf diesen Proxy-Typ geändert werden. Wenn Sie in einer Referenz lesen, die nicht bereits in der Karte ist, können Sie einen Proxy erstellen und den Proxy verwenden. Wenn Sie ein Zeichen laden, die Sie bereits einen leeren Proxy in der Karte haben, füllen Sie es mit Ihrem neu geladenen Charakter. Sie können auch einen Zähler hinzufügen wollen, um zu verfolgen, wie viele leere Proxy Sie in der Karte, so dass Sie wissen, wenn alle referenzierten Zeichen geladen wurden.

Eine weitere Schicht der Dereferenzierung .... es immer einfacher und langsame Programmierung.

Eine Möglichkeit wäre, die Verpflichtung aufzuheben. Die Karte ist für die in der Referenz Füllung

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()
}

, die mit dem Wert / Verschieben Semantik nicht interagieren gut, aber ich vermute, dass nicht viel Willen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top