Fragen zu nem Spielablauf....



  • wow ich bin sprachlos 🙂

    Sowas nenn ich mal professionelle Hilfe!!! dank dir , werde es so bearbeiten.

    Falls ich nochmal Fragen habe, komme ich gerne wieder auf dich zu!!

    thx lg mano



  • Oh wei..

    Wenn ich das mit den Funktionen mache, bekomme ich nur Fehler raus...

    #include <iostream>
    #include <windows.h>
    
    using namespace std;
    
    //Funktionen
    
    void Credits ();
    void Zeigemenu ();
    void Warten ();
    
    int main ()
    {
    	Zeigemenu ();
    	Warten ();
    	return 0;
    
    }
    
    void Credits ()
    {
    	cout << "????? Beta v1.0" << endl;
    	cout << "written by mano_zenn";
    	cout << "\n\n";
    
    }
    
    void Zeigemenu ()
    {
    	char Auswahl;
    
    	do
    	{
    		cout << "??????????????" << endl;
            cout << "--------------" << endl;
            cout << "(N)eues Spiel" << endl;
            cout << "(O)ptionen" << endl;
            cout << "(I)nfos" << endl;
            cout << "(B)eenden" << endl;
    
            cout << "Auswahl: ";
            cin >> Auswahl; 
    
    		switch (Auswahl)
            {
            case ('n'):
            case ('N'):
                {       
    
                cout << "Bitte erstellen Sie einen Charakter" << endl;
    
                            //NeuerChar ()
    
                ;}break;
    
            case ('o'):
            case ('O'):
                {
    
    			}break;
    
            case ('i'):
            case ('I'):
                {
    
    				        Credits ();
    
                }break;
    
            case ('b'):
            case ('B'):
                {
    
                    // Hier soll er ja beenden, geht aber nicht die Schleife läuft immer weiter...    
    				cout << "Bis zum naechsten Mal" << endl;
    				return 0; // Damit er beendet ?? kommt aber der Fehler void -Funktionen gibt hier einen Wert zurück...
    
                }break;
    
            default :
                {
                cout << "Ungueltige Eingabe" << endl;
    
                }
    
            }
    
        }while (Auswahl != 'b' || Auswahl != 'B');
    
        cout << "Bis zum naechsten Mal" << endl;
    
    }
    
    void Warten()
    {
        // Für eine Erklärung siehe Konsolen-FAQ (Automatisches Schließen
        // verhindern)
        cin.clear();
        cin.ignore(cin.rdbuf()->in_avail());
        cin.get();
    }
    


  • Was für Fehler denn genau?

    $ g++ main.cpp
    main.cpp: In function »void Zeigemenu()«:
    main.cpp:88: Fehler: Return-Anweisung mit Wert in »void« zurückgebender Funktion
    

    Ersetz mal das return 0 durch ein std::exit(0); bzw exit(0); und schreib am Anfang noch #include <cstdlib> dazu

    EDIT://

    Ein return; solle das auch erledigen und ist uU besserer Stil, frag mich nicht 😉



  • Void -Funktion gibt einen Wert zurück...

    siehe Deklaration von 'Zeigemenu'

    Aber ich will ja erreichen, dass wenn man auf B drückt die Meldung kommt, bis zum nächsten Mal .... und er das Prog beendet.

    Irgendwie geht das nicht, aber erst seitdem ich das Hauptmenu mit Funktionen aufrufe und nicht direkt den switch - case block in die main - Fuktion schreibe.

    Die Schleife soll so lange laufen, bis der benutzer b oder B drückt ... dann soll er das Programm beenden.

    geht das nicht mit return 0;



  • Schau dir mal an, ob das , was ich in meinen Beitrag editiert habe, hilft 😉



  • Ne geht auch nicht^^

    Mhm verstehe ich nicht. Also ich verstehe die Meldung schon...

    Die Funktion ist ja void darf daher keinen Wert zurück geben... Aber wie soll das sonst gehen....

    Wenn ich das in der main Funktion schreibe geht alles.... dann schreibe ich einfach hinter die while Schleife...

    return 0; und er beendet ... aber hier geht das irgendwie nicht.



  • #include <iostream> 
    #include <cstdlib>
    
    using namespace std; 
    
    //Funktionen 
    
    void Credits (); 
    void Zeigemenu (); 
    void Warten (); 
    
    int main () 
    { 
        Zeigemenu (); 
        Warten (); 
        return 0; 
    
    } 
    
    void Credits () 
    { 
        cout << "????? Beta v1.0" << endl; 
        cout << "written by mano_zenn"; 
        cout << "\n\n"; 
    
    } 
    
    void Zeigemenu () 
    { 
        char Auswahl; 
    
        do 
        { 
            cout << "??????????????" << endl; 
            cout << "--------------" << endl; 
            cout << "(N)eues Spiel" << endl; 
            cout << "(O)ptionen" << endl; 
            cout << "(I)nfos" << endl; 
            cout << "(B)eenden" << endl; 
    
            cout << "Auswahl: "; 
            cin >> Auswahl; 
    
            switch (Auswahl) 
            { 
            case ('n'): 
            case ('N'): 
                {       
    
                cout << "Bitte erstellen Sie einen Charakter" << endl; 
    
                            //NeuerChar () 
    
                ;}break; 
    
            case ('o'): 
            case ('O'): 
                { 
    
                }break; 
    
            case ('i'): 
            case ('I'): 
                { 
    
                            Credits (); 
    
                }break; 
    
            case ('b'): 
            case ('B'): 
                { 
    
                    // Hier soll er ja beenden, geht aber nicht die Schleife läuft immer weiter...     
                    cout << "Bis zum naechsten Mal" << endl; 
                    exit( 0 ); // Damit er beendet ?? kommt aber der Fehler void -Funktionen gibt hier einen Wert zurück... 
    
                }break; 
    
            default : 
                { 
                cout << "Ungueltige Eingabe" << endl; 
    
                } 
    
            } 
    
        }while (Auswahl != 'b' || Auswahl != 'B'); 
    
        cout << "Bis zum naechsten Mal" << endl; 
    
    } 
    
    void Warten() 
    { 
        // Für eine Erklärung siehe Konsolen-FAQ (Automatisches Schließen 
        // verhindern) 
        cin.clear(); 
        cin.ignore(cin.rdbuf()->in_avail()); 
        cin.get(); 
    }
    

    Compiliert bei mir genauso wie

    #include <iostream> 
    #include <cstdlib>
    
    using namespace std; 
    
    //Funktionen 
    
    void Credits (); 
    void Zeigemenu (); 
    void Warten (); 
    
    int main () 
    { 
        Zeigemenu (); 
        Warten (); 
        return 0; 
    
    } 
    
    void Credits () 
    { 
        cout << "????? Beta v1.0" << endl; 
        cout << "written by mano_zenn"; 
        cout << "\n\n"; 
    
    } 
    
    void Zeigemenu () 
    { 
        char Auswahl; 
    
        do 
        { 
            cout << "??????????????" << endl; 
            cout << "--------------" << endl; 
            cout << "(N)eues Spiel" << endl; 
            cout << "(O)ptionen" << endl; 
            cout << "(I)nfos" << endl; 
            cout << "(B)eenden" << endl; 
    
            cout << "Auswahl: "; 
            cin >> Auswahl; 
    
            switch (Auswahl) 
            { 
            case ('n'): 
            case ('N'): 
                {       
    
                cout << "Bitte erstellen Sie einen Charakter" << endl; 
    
                            //NeuerChar () 
    
                ;}break; 
    
            case ('o'): 
            case ('O'): 
                { 
    
                }break; 
    
            case ('i'): 
            case ('I'): 
                { 
    
                            Credits (); 
    
                }break; 
    
            case ('b'): 
            case ('B'): 
                { 
    
                    // Hier soll er ja beenden, geht aber nicht die Schleife läuft immer weiter...     
                    cout << "Bis zum naechsten Mal" << endl; 
                    return; // Damit er beendet ?? kommt aber der Fehler void -Funktionen gibt hier einen Wert zurück... 
    
                }break; 
    
            default : 
                { 
                cout << "Ungueltige Eingabe" << endl; 
    
                } 
    
            } 
    
        }while (Auswahl != 'b' || Auswahl != 'B'); 
    
        cout << "Bis zum naechsten Mal" << endl; 
    
    } 
    
    void Warten() 
    { 
        // Für eine Erklärung siehe Konsolen-FAQ (Automatisches Schließen 
        // verhindern) 
        cin.clear(); 
        cin.ignore(cin.rdbuf()->in_avail()); 
        cin.get(); 
    }
    

    Was hast du denn für neue Fehlermeldungen?



  • Ja so kompiliert er auch bei mir, also ohne return 0;

    ich will aber das dass Programm beendet wird sobald b bzw. B gedrückt wird...



  • Bei mir beenden sich auch beide wenn ich auf B drücke ...



  • Verstehe ich nicht... bei mir läuft die Schleife einfach munter weiter^^



  • Hast du meins kopiert? 1:1?



  • Ok danke darth jetzt gehts.... Es lag an return 0;

    einfach return; ... liegt wahrscheinlich daran das void keinen wert zurückgeben darf... weil die Funktion halt leer ist ^^



  • So hat bis jetzt alles geklappt, dass einzige was ich nicht ganz verstehe ist die Auslagerung von Dateien....

    Mein Code sieht wie folgt aus.

    Erst die Main datei!

    #include <iostream>
    #include <Charakter.h>
    [e]
    
    using namespace std;
    
    //Funktionen
    
    void Credits ();
    void Zeigemenu ();
    void Warten ();
    int NeuerChar ();
    
    int main ()
    {
        Zeigemenu ();
        Warten ();
        return 0;
    
    }
    
    void Credits ()
    {
        cout << "????? Beta v0.1" << endl;
        cout << "written by mano_zenn";
        cout << "\n\n";
    
    }
    
    void Zeigemenu ()
    {
        char Auswahl;
    
        do
        {
            cout << "??????????????" << endl;
            cout << "--------------" << endl;
            cout << "(N)eues Spiel" << endl;
            cout << "(O)ptionen" << endl;
            cout << "(I)nfos" << endl;
            cout << "(B)eenden\n\n" ;
    
            cout << "Auswahl: ";
            cin >> Auswahl;
    
            switch (Auswahl)
            {
            case ('n'):
            case ('N'):
                {      
    
                cout << "Bitte erstellen Sie einen Charakter" << endl;
    
    		   //NeuerChar () Das soll eine neue Funktion werden die in der Funktion verzweigt ist... geht das ??
    
                       NeuerChar ();
    
    			;}break;
    
            case ('o'):
            case ('O'):
                {
    
                }break;
    
            case ('i'):
            case ('I'):
                {
    
                            Credits ();
    
                }break;
    
            case ('b'):
            case ('B'):
                {
    
                    // Hier soll er ja beenden, geht aber nicht die Schleife läuft immer weiter...    
                    cout << "Bis zum naechsten Mal" << endl;
                    return; 
    
                }break;
    
            default :
                {
                cout << "Ungueltige Eingabe" << endl;
    
                }
    
            }
    
        }while (Auswahl != 'b' || Auswahl != 'B');
    
        cout << "Bis zum naechsten Mal" << endl;
    
    }
    
    void Warten()
    {
        // Für eine Erklärung siehe Konsolen-FAQ (Automatisches Schließen
        // verhindern)
        cin.clear();
        cin.ignore(cin.rdbuf()->in_avail());
        cin.get();
    }
    

    Headerdatei Charakter.h!

    #if !defined(CHARACTER_HEADER)  // <-- Inklude Guards, mehr später
    #define CHARACTER_HEADER
    
    #include <string> // Für std::string
    
    struct Charakter
    {
    
        int Gesundheit; // Zuweisung ist hier nicht möglich
        int Energie;
        std::string Name;
        std::string Klasse;
    
        // Für initialisierungen benutzt man einen Konstruktor bei Klassen
        // Strukturen:
        Charakter()  // Konstruktor heißt wie Struktur
        :  Gesundheit(150),  // Initialisierungsliste
           Energie(75),
           Name(),
           Klasse() 
    
     ;}
    #endif
    

    und halt noch die Quellcodedatei Charakter.cpp

    #include "Charakter.h"
    
    ;using namespace std;
    
    int NeuerChar ();
    
    {
    }
    

    Was ich nicht verstehe ist, in der Headerdatei ist jetzt die Struktur und auch die Intialisierung und alles. So die hab ich ja jetzt immer parat und kann sie in meine Projekte einbringen durch #inlude <Charakter.h>

    Aber wie kann ich die Funktion jetzt ausführen... Muss ich die Funktion jetzt in Charakter.cpp schreiben ? Charakter.h ist ja nur die Struktur ich will aber, dass wenn man in der main auf Neues Spiel geht, dass dann die Funktion aufgerufen wird. Und man seinen Namen, die Klasse .. usw eingeben muss und es dann auch ausgeben wird.

    Wie muss ich das jetzt in die Charakter.cpp schreiben, damit ich diese Funktion später in der main aufrufen kann ??



  • mano_zenn schrieb:

    So hat bis jetzt alles geklappt, dass einzige was ich nicht ganz verstehe ist die Auslagerung von Dateien....

    Ich weiß das es dir in den Fingern juckt, aber bitte lies dir mal ein Tutorial wirklich durch wo die Grundlagen beschrieben sind. Ich werde zwar nochmal antworten, aber dir fehlen einfach noch viele wichtige Grundlagen.

    Auslagern von Dateien
    Die Verteilung in mehrere Dateien hat zum einen den Sinn, den Code besser zu strukturieren, zum anderen um Codebestandteile an mehreren Stellen verwenden zu können.

    Dabei gibt es in C++ in der Regel eine Trennung in Header (meist .h) und Source (meist .cpp). Ausnahmen stellen Templatedefinitionen (hast du noch nicht, daher erstmal nur der vollständigkeit halber) dar, die man komplett im Header schreiben sollte.

    Was gehört nun in den Header und was in den Source?

    1. Grobe Untergliederung
    Im Header sollte die Deklaration, im Source die Definition stehen. In der Regel sollte man eine grobe Richtlinie haben, die Wildwuchs ein bischen begrenzt und das ganze Überschaubar hält. Normalerweise tut man jeweils eine Klasse (oder komplexere Struktur) in eine eigene Codeeinheit (.h/.cpp) und zusammenhängende Funktionen tut man auch in überschaubarer Anzahl in einzelne Codeeinheiten. Dü könntest z.B. deine Menüfunktionen in eine solche Codeeinheit (z.B. menu.h...) packen.

    2. Eigentlicher Inhalt
    a) Jeder Header sollte mit einem Includeguard geschützt werden. Dabei ist darauf zu achten das eindeutige Makronamen verwendet werden.
    b) In der Sourcedatei ist immer der zugehörige Header zu inkludieren
    c) Includes sollten soweit möglich erst in der Source-Datei gemacht werden, und nur wo nötig im Header (reduziert u.a. die Linkzeiten und vermeidet zyklische Abhängigkeiten)
    d) Im Header sollte möglichst nur die Deklaration stehen

    3. Beispiel
    Am einfachsten ist das Ausgliedern von Funktionen zu verstehen, da du etwas in der Art eh schon machst (Vorwärtsdeklaration von Funktionen):

    Header (menue.h)

    #if !define(MENUE_HEADER)  // alternativ: #ifndef MENUE_HEADER
    #define MENUE_HEADER
    
    // Deklaration so wie vorher in der main.cpp oder wie die bei dir heißt ;)
    void Credits();
    void Zeigemenu();
    void Warten();
    int NeuerChar();
    
    #endif
    

    Sorce (menue.cpp)

    #include "menue.h"
    // <-- weitere Includes
    
    void Credits()
    {
      // <-- Eigentlicher Code von der Funktion
    }
    // ...
    

    Bei Strukturen und Klassen ist es ähnlich, nur muss außerhalb der Klasse sichtbar sein welche Methoden (Funktionen der Struktur/Klasse) zu welcher Klasse gehören. Dies macht man dadurch in dem man den Klassennamen vor den Methodennamen schreibt und mittels Scopeoperator :: verbindet

    Anmerkung: In C++ sind Strukturen und Klassen nahezu identisch, wundere dich nicht wenn ich ab und zu in den Begriff Klasse abrutsche... den Unterschied schreibe ich dir noch im P.S. dieses Beitrages als kleinen Vorgriff auf die Zukunft.

    Initialisierungen gehören wenn möglich auch in den Source, du hast es nicht wie von mir geschrieben übernommen, sondern zerrissen ;P (Du hast aus zwei Teilbeispielen eins gemacht, und dieses dann als Kombination aus beiden zusammengesetzt, siehst du aber vielleicht im folgenden selbst)

    Header (foo.h)

    #if !define(FOO_HEADER)
    #define FOO_HEADER
    
    struct Foo
    {
        int A;
        int B;
    
        int GetA() const;  // Beispiel für eine "normale" Funktion einer Klasse, einer "Methode"
        // const da es keinen Wert ändert
    
        Foo();             // Standardkonstruktor (spezielle Methode, keine Angabe Rückgabewert)
        Foo(int a, int b); // Konstruktor mit Parametern (spezielle Methode)
    };
    
    #endif
    

    Sorce (foo.cpp)

    #include "foo.h"
    
    // Klassenname muss vor die Methode geschrieben werden
    int Foo::GetA() const
    {
        return A; // nicht-statische Methoden können direkt auf die Member zugreifen
    }
    
    // Konstruktoren können als einzige Initialisierungslisten besitzen
    Foo::Foo()
    :  A(12), B(24)
    {
    }
    
    Foo::Foo(int a, int b)
    :  A(a), B(b)
    {
    }
    

    So, nun gehen wir auf deine Problem ein:

    mano_zenn schrieb:

    Was ich nicht verstehe ist, in der Headerdatei ist jetzt die Struktur und auch die Intialisierung und alles. So die hab ich ja jetzt immer parat und kann sie in meine Projekte einbringen durch #inlude <Charakter.h>

    Aber wie kann ich die Funktion jetzt ausführen... Muss ich die Funktion jetzt in Charakter.cpp schreiben ? Charakter.h ist ja nur die Struktur ich will aber, dass wenn man in der main auf Neues Spiel geht, dass dann die Funktion aufgerufen wird. Und man seinen Namen, die Klasse .. usw eingeben muss und es dann auch ausgeben wird.

    Wie muss ich das jetzt in die Charakter.cpp schreiben, damit ich diese Funktion später in der main aufrufen kann ??

    Ein Teil sollte dir am Beispiel klar werden. Da ich ungern fertige Lösungen präsentiere sondern immer gerne das mitdenken anrege, zeige ich dir mal wie man nun die Struktur Foo und deren Methoden verwenden kann:

    main.cpp

    #include "foo.h"
    
    int main()
    {
        // Als erstes legen wir ein Objekt der Klasse foo an:
        Foo a;
        // Was ist nun in der Zeile genau passiert? Es fand dank einer
        // Standardkonstruktordefinition nämlich etwas im Hintergrund statt
        // (Anmerkung: Entferne mal zum Test den Konstruktor ohne Parameter
        // aus Foo und prüfe mal was dann passiert: Richig, es lässt sich
        // kein Objekt so ("Foo a;") mehr anlegen.
        //
        // Also nochmal in aller Kürze:
        // Foo a; Legt ein Objekt der Struktur Foo an. Da hier keine weitere
        // Angabe erfolgt, wird die Struktur über den Standardkonstruktor
        // angelegt. Sprich: ohne es zu sehen wird Foo::Foo() aufgerufen!
        // Somit ist a.A 12 und a.B 24, wie in der Initialisierungsliste
        // angegeben
    
        // So, nun wollen wir mal eine Methode von Foo expliziet aufrufen
        int b = a.GetA(); // Dies ruft Foo::GetA() von der Instand a auf ;)
    
        // Nun zeigen wir mal den zweiten Konstruktor:
        Foo c(1,2); // Dieses mal wird c über den Konstruktor Foo::Foo(int a, int b)
        // angelegt...
    
        b = a.A; // Direkter zugriff auf den öffentlichen Member "A" von der
        // Instanz a
    }
    

    So... das erstmal wieder als Vorlage 😉

    Gerne konkrete Fragen aber bitte nicht blind abschreiben ohne es zu verstehen, lieber nochmal zu einen Thema fragen.

    cu André
    P.S: Keiner Vorgriff: Was ist der Unterschied zwischen einer Struktur und einer Klasse in C++?
    Im wesentlichen sind Strukturen und Klassen identisch, mit Ausnahme der Sichtbarkeit. In Strukturen ist im Standardfall jeder Zugriff von außen erlaubt (sprich: du kannst auf alles von außen zugreifen wie z.B. im Beispiel über a.A, a.GetA()...) in Klassen ist erstmal der Zugriff verboten. Diese Sichtbarkeit kann man aber explizit für Teile ändern.


Anmelden zum Antworten