Anfängerfrage zum Thema Daten sortieren und abrufen



  • Huhu,

    ich bin derzeit dabei, ein eigenes kleines Text-RPG zu schreiben (mehr eine Kampfsimulation), bei der der Spieler seiner Figur einen Namen geben und Charakterklasse sowie Waffe auswählen kann, um anschließend in einen rundenbasierenden Kampf ziehen kann.

    Nun war meine Idee, dass ich die wählbaren Waffen, Charakterklassen und Gegner in je einer Datei definiere (für jede Waffe, jeden Beruf und jeden Gegner eine eigene Klasse). Wählt der Spieler etwas aus, wird seine Wahl natürlich in einer Variablen gespeichert und die entsprechenden Werte werden geladen - im Grunde also alles ganz normal.
    Nun müsste ich allerdings für jede Waffe/Charakterklasse/jeden Gegner eine eigene if-Anweisung oder besser einen Block in einer Switch-Anweisung formulieren. "Wählt der Spieler Waffe 1, dann weise seiner Angriffsstärke die Stärke von Waffe 1 aus Klasse 1 zu. Wählt er Waffe 2, dann......."
    Das kommt mir allerdings sehr umständlich vor. Ich hatte irgendwie gehofft, es gibt eine Methode, mit der ich beispielsweise jeder Waffe eine Kennziffer verpassen kann. Entspricht die Variable "Chosen_Weapon" dann einer dieser Ziffern, werden die Werte der jeweiligen Waffe automatisch dem Spieler zugewiesen.

    Also wie jedem aufgefallen sein dürfte, bin ich eher Anfänger und meine Formulierungen sind daher noch etwas Naiv. Ich hoffe aber, dass jeder versteht, worauf ich hinaus möchte und mir vielleicht auch nur ein Stichwort geben kann, unter dem ich eventuell eine Lösung finden kann.

    Beste Grüße
    Christian



  • Du könntest die Charakterklassen und Gegner in je einem Array speichern und dann über den Index (deine "Kennziffer") darauf zugreifen.

    z.B.

    Charakter AlleCharaktere[5]; // dein Array von Charakter-Instanzen
    // dieses musst du noch initialisieren
    AlleCharaktere[0].Eigenschaft = 4; // dann greifst du auf das entsprechende Element zu
    


  • ich bin gerade an einem ähnlichen Projekt und mache das mit einer switch Anweisung... da ich dies am leichtesten zu proggen finde.... das Verständnissproblem habe ich über Klassen gelöst und auslagerung in Headerdateien... Desweiteren benutze ich die Möglichkeit der Vererbung... also z.b. ist die Klasse Weaponset (also die ausgewählte waffe und deren Eigenschaften) eine eigenschaft der Klasse player (also die Spielerklasse)..... Wenn du schon was mit dem Begriff Vererbung anfangen kannst (weiss ja nicht wie weit du schon gekommen bist) dann würde ich dir natürlich meine idee emfehlen 😉

    Wenn nicht würde ich dennoch über die switch anweisung arbeiten, da dies (meiner Meinung nach) wesentlich übersichtlicher und leichter zu schreiben ist als der Arrayvorschlag....

    PS: Das definieren der Gegner kannst du über eine Methode lösen... dann musst du die Methode nur mit den entsprechenden Daten aufrufen... das kann dir viel Tipparbeit ersparen... aber da bist du sicher schon selber drauf gekommen 😉



  • Das nenn ich mal flotte Antworten.
    Danke schonmal 🙂

    Arrays sind da wohl tatsächlich etwas unübersichtlich, wobei ich das trotzdem im Hinterkopf behalten werde. Das RPG soll zusammen mit meinen Fähigkeiten wachsen - als Zeugnis für meine Fortschritte sozusagen - da kann das schon ganz praktisch sein.
    Aber mir fällt ein, dass man es vielleicht über Strukturen lösen kann. Dann kann ich auch Beispielsweise den Namen der Waffe/Klasse/des Gegners sowie eine kurze Beschreibung reinschreiben. Da bliebe halt nur weiterhin die Frage, ob ich dem Programm irgendwie klar machen kann, dass es die kompletten Werte der Waffe, die natürlich einer gleichnamigen Strukturen entspricht, automatisch zuweisen soll. (Nicht irritiert sein. Das war jetzt mehr schriftlich gedacht - ein Monolog sozusagen.)
    Also irgendwie habe ich das Gefühl, dass ich noch ein wenig lernen sollte, bevor ich mich damit beschäftige, wie ich einen 'perfekten' Code formuliere 😃

    Vorerst werde ich es wirklich mit switch lösen.



  • Sorry, es ist sehr gut möglich, dass ich etwas falsch verstanden habe. Jedoch sind deine Beschreibungen auch nicht gerade leicht verständlich, du bringst einige Begriffe (z.B. "Klasse") ein wenig durcheinander.

    Soweit wie ich verstanden habe, wäre es möglicherweise einfacher mit Arrays.
    Poste doch einfach mal den Code, so wie du es mit switch machen würdest, damit das Prinzip klar ist. Gut möglich, dass sich da noch etwas optimieren lässt, doch ohne Code kann ich mir es auch nicht genau vorstellen...



  • Jud4s schrieb:

    [...] benutze ich die Möglichkeit der Vererbung... also z.b. ist die Klasse Weaponset (also die ausgewählte waffe und deren Eigenschaften) eine eigenschaft der Klasse player (also die Spielerklasse)[...]
    )

    Ist das denn wirklich sinnvoll? Player erbt also von einem Waffenset, das bedeutet, Player ist ein Waffenset. Macht das wirklich Sinn?



  • Eben solche Sachen meine ich unter anderem - von Design keine Spur (soll jetzt nicht böse gemeint sein) 😉
    Die sprachliche Unklarheit kommt noch dazu.

    @ FoxY: Verdeutliche deinen Programmaufbau an einem Stück Quellcode.



  • Huhu,

    ich hatte schon irgendwie erwartet, dass meine Ausdrucksweise für einige Missverständnisse sorgen wird 😃
    Ich war bei meinem Spiel bisher noch nicht bei den Waffen, deshalb hab ich den wesentlichen Code erstmal improvisiert.

    cout << "Bitte wählen sie eine Waffe (Nummer eingeben und Enter drücken): " << endl;
    cout << "1 Schwert, 2 Knüppel, 3 Axt" <<endl;
    
    RETRY:                        //Wird bei einer falschen Eingabe angesteuert.
    cin >> Chosen_Weapon;
    
    switch(Chosen_Weapon)
    {
          case 1:
               Player_dmg = 4;
               break;
          case 2:
               Player_dmg = 6;
               break;
          case 3:
               Player_dmg = 8;
               break;
    
          default:         //Fehlerhafte Eingabe
                cout << "Bitte 1, 2 oder 3 eingeben!" << endl;
                goto RETRY;
    }
    

    Ich könnte die einzelnen Waffen auch in einer externen Datei in einem 'Päckchen' (beispielsweise einer eigenen Klasse) definieren können, aber trotzdem müsste ich für jede Wahlmöglichkeit einen eigenen Case schreiben.

    Solange es nur bei drei Waffen bleibt und diese sich auch nur in der Angriffsstärke unterscheiden, kann ich das natürlich so machen. Aber wie schon erwähnt, soll das ganze noch wachsen. Es wird zwar weiterhin auf Text basieren, aber es bekommt eine ansprechende grafische Oberfläche, eine Story und tatsächlich mehr als nur drei Waffen, die auch komplexer werden.
    Irgendwie glaube ich einfach nicht, dass ich 200 oder mehr Anweisungen (für jede Waffe eine) formulieren muss. Deshalb hatte ich gehofft, ich könnte jeder eine Art Index zuweisen und dann eine Funktion definieren, die soviel aussagt wie: "Weise dem Spieler den Datenbehälter (die Waffe) zu, die den Index trägt, welche der Eingabe entspricht". Welche Form der 'Behälter' nun haben wird, weiß ich noch nicht - ob eine Klasse, eine Struktur etc.



  • Oder eben ein Array, was wahrscheinlich das Einfachste wäre. Ich begreife deinen Einwand nicht, Jud4s. Ein switch -Block wäre hier definitiv an der falschen Stelle.
    Ausserdem ist ein goto nie gut, da es sehr schnell zu Verhalten führen kann, das du nicht mehr nachvollziehen kannst. Deshalb habe ich eine Do-While-Schleife geschrieben. Diese wird so lange wiederholt, bis die Bedingung am Schluss wahr ist.

    int DamageArray[] = {4, 6, 8, 13, 14, 25}; // 6 Waffen; Index von 0 bis 5
    
    do
    {
       cout << "Bitte Zahl zwischen 1 und 6 eingeben: ";
       cin >> Chosen_Weapon; // Eingabe zwischen 1 und 6
    } while (!(Chosen_Weapon >= 1 && Chosen_Weapon <= 6)); // wenn nicht Eingabe zw. 1 und 6, dann wiederholen
    // gleichwertige Alternative: while (Chosen_Weapon < 1 || Chosen_Weapon > 6); 
    
    Player_dmg = DamageArray[ChosenWeapon-1]; // Hier greifst du auf das Array zu (der Index steht in den []-Klammern)
    // ChosenWeapon-1, weil du ja Eingaben von 1 bis 6 statt 0 bis 5 machst
    

    Falls noch Verständnisfragen auftreten, schreib einfach.



  • Also, wenn ich das richtig abschätze, dann kann ich für jede Eigenschaft, die die Waffen haben sollen ein eigenes Feld machen - oder ich mach ein Array mit mehreren Dimensionen (berichtigt mich nur, wenn die Überlegung falsch sein sollte *g*).
    Einfach, aber genial. Danke 🙂



  • Oder auch irgendwie so:

    struct Weapon
    {
        std::string name;
        int         dmg;
        // Weitere Eigenschaften..
    
        Weapon() {} // Standard-Konstruktor
    
        Weapon( std::string n, int d ) : name(n), dmg(d) {}
    
        bool operator==( const Weapon& other ) const
        { return name == other.name; }
    };
    
    std::map<std::string,Weapon> weapons;
    
    // irgendwo Waffen 'laden':
    weapons["Schwert"] = Weapon( "Schwert", 17 );
    weapons["Dolch"] = Weapon( "Dolch", 6 );
    
    Weapon chooseWeapon()
    {
        std::cout << "Verfügbare Waffen: " << std::endl;
        for ( std::map<std::string,Weapon>::const_iterator i=weapons.begin(); i!=weapons.end(); i++ )
            std::cout << "  " << i->first << " (" << i->second.dmg << " Schaden)" << std::endl;
    
        std::string choice;
        bool weapon_found = false;
        do
        {
            std::cout << "Bitte eine Waffe auswählen: ";
            std::cin >> choice;
    
            if ( weapons.find(choice) != weapons.end() )
                weapon_found = true;
            else
                std::cout << "Ungültige Eingabe, bitte nochmal versuchen" << std::endl;
    
        } while ( ! weapon_found );
    
        return weapons[choice];
    }
    

    edit: Bzw kannst du auch einen std::vector statt einer std::map benutzen, kommt aber halbwegs aufs selbe raus.

    edit2: :p Dafür hat Nexus in seinem Post den sequenziellen Zugriff drin, das ist für einen Anfänger wahrscheinlich eine Ecke einfacher 🙂



  • FoxY schrieb:

    Also, wenn ich das richtig abschätze, dann kann ich für jede Eigenschaft, die die Waffen haben sollen ein eigenes Feld machen - oder ich mach ein Array mit mehreren Dimensionen (berichtigt mich nur, wenn die Überlegung falsch sein sollte *g*).
    Einfach, aber genial. Danke 🙂

    Ja, das wäre eine Möglichkeit. Wenn du allerdings mehrere Eigenschaften hast, lohnt es sich mit der Zeit, ein Array von Klasseninstanzen machen. Ich weiss nicht, ob du dich mit Klassen bereits auskennst, ansonsten ist das mit dem Array vielleicht eine gute Übung.

    Mit Klassen ginge es etwa so:

    struct Waffe
    {
       std::string Name;   // Halt irgendwelche Eigenschaften
       int Schaden;
       int Kosten;
       Waffe(std::string NeuerName, int NeuerSchaden, int NeueKosten) // Konstruktor
       : Name(NeuerName), Schaden(NeuerSchaden), Kosten(NeueKosten) {};
    };
    
    int main()
    {
       Waffe WaffenArray[7];
       WaffenArray[0].Waffe("Schwert", 4, 250);
       WaffenArray[1].Waffe("Speer", 7, 350);
       // und so weiter
       int WaffenName, WaffenSchaden, WaffenKosten;
       // hier käme die Eingabe der Nummer mit allem drum und dran;
       cin >> Index; // halt zwischen 0 und 7
       MeinName = WaffenArray[Index].Name; // hier könntest du auf die Klassenmember zugreifen
       MeinSchaden = WaffenArray[Index].Schaden;
       MeineKosten = WaffenArray[Index].Kosten;
    }
    

    Oder du könntest noch extra Funktionen dazu machen...

    Edit: Verdammt, zu spät 😉



  • Die letzten beiden Beispiele kann ich jetzt noch etwas schwer einschätzen. Ich weiß zwar, was Strukturen, Klassen usw. sind, aber die Möglichkeiten sind mir in ihrer vollen Pracht noch ein Rätsel 😕

    Ich glaub, da muss ich mich erstmal noch ein wenig reinlesen.



  • Ja, falls du noch nicht gross mit Klassen gearbeitet hast, sind unsere Methoden nicht unbedingt geeignet. Vorläufig würde ich es entweder bei einem 2D-Array oder mehreren eindimensionalen Arrays belassen, dann vertiefst du auch gerade ein anderes wichtiges Kapitel von C++ 😉



  • Achja, eine kleine Frage hätte ich da noch. Es hat eigentlich nicht wirklich mit dem bisherigen Thema zu tun, aber ich wollte keinen extra Thread dafür eröffnen.

    Und zwar benutze ich Dev-C++. Wenn ich da versuche zu debuggen taucht die Meldung auf, dass in dem Programm keine Debugging Informationen erhalten sind und ob ich erneut Kompilieren und Debugging aktivieren möchte. Bringt aber nichts, wenn ich bestätitge.
    Mir ist nicht ganz klar, was er da für Informationen braucht.



  • Passiert das nicht nur, wenn du versuchst, von einem Header aus zu kompilieren? Machs mal von einer .cpp-Datei aus...

    Ich hatte früher auch Dev-C++, aber bin auf Microsoft Visual C++ 2008 Express umgestiegen. Das würde ich dir auch empfehlen, der ist nämlich moderner und bietet mehr Funktionen und Benutzerfreundlichkeit (z.B. IntelliSense).



  • Darauf hab ich auf Grund persönlicher Antipathien gegen Microsoft verzichtet *g*
    Aber sieht wohl so aus, als wäre Visual C++ ein Grund, mal zähneknirschend über den Stolz hinwegzusehen.



  • FoxY schrieb:

    Darauf hab ich auf Grund persönlicher Antipathien gegen Microsoft verzichtet *g*
    Aber sieht wohl so aus, als wäre Visual C++ ein Grund, mal zähneknirschend über den Stolz hinwegzusehen.

    Guck Dir mal Codeblocks an. Das sollte ausreichend sein.



  • Du musst es natürlich selber wissen, ich finde VC++ eigentlich okay, und Dev-C++ ist wirklich mühsam dagegen... Ich würde VC++ einfach mal ausprobieren, und sonst kannst du ja immer noch zurückwechseln 😉

    Ansonsten gibt es z.B. noch Code::Blocks und einige weitere Entwicklungsumgebungen.
    Dev-C++ hat einfach das Problem, dass er veraltet ist. Teilweise werden auch gewisse Features nicht unterstützt (und er hat - glaube ich - auch einige Bugs).



  • Also ich hoffe mal, ich nerve nicht mit meinen häufigen Fragen, aber ich hätte noch eine - diesmal aber aus reiner Neugierde.

    Wie werde solche Dinge eigentlich in professionellen Projekten gelöst? Das letzte mal, als ich in einem kommerziellen Spiel rumgeschnüffelt hab (nur mit legalen Methoden, versteht sich), habe ich nur einfache Tabellen gefunden, wie man sie in jedem Textdokument vermuten könnte. Die enthielten ebenfalls alle Daten, die ich jetzt in Arrays stopfe.

    Im Übrigen auch Danke für den Ratschlag bezüglich Visual C++. Der Editor allein ist schon übersichtlicher, von dem ganzen Zucker drum herum garnicht zu sprechen.


Log in to reply