Der beste Weg zum Spieleprogrammieren



  • Vor der nächsten Aufgabe hätte ich da nochmal eine Frage.
    Dieses Auslesen einer Datei kann man doch (auch) dazu benutzen um Spielstände zu laden, richtig? Dann müsste man für das Speicher die Datei einfach ändern bzw. neu beschreiben, oder?

    Weiterhin danke für eure Hilfe.

    -Skotchy



  • Will mich nicht großartig einmischen, finde gut, dass du ihm hilfst, habe nur mal an dich (cooky451) ne Frage ..

    cooky451 schrieb:

    ifstream hat einen Konstruktor, da brauchst du dann kein open mehr:

    ifstream datei("text.txt");
    

    Das close am Ende kannst du hier auch sparen, das macht der Destruktor. (RAII ist schon was Tolles. :p)

    Gehen wir davon aus wir haben einen Gültigkeitsbereich, in dem ein Stream geöffnet wird. Irgendwo zwischendrin schmiert das Programm ab, ohne eine Exception zu werfen. Die Dateioperationen sind längst abgeschloßen. Was ist die Folge: Destruktor wird nicht aufgerufen, Datei wird nicht geschloßen, lässt sich vom User nicht mehr bearbeiten/verschieben/löschen weil Windoof sagt "Datei in Verwendung". Warum dann kein close () verwenden um sowas zu vermeiden? Oder sehe ich da was Falsch?

    Also z.B.

    { // Gültigkeitsbereich
        ifstream bla ("datei.txt");
    
        /* Mache hier alle gewünschten Operationen mit der Datei */
    
        /* Hier könnte jetzt ein bla.close () rein, weil alle Dateioperationen erledigt wurden */
    
        /* Hier schmiert das Programm ab, ohne Exception, d.h. Destruktor für bla wird nicht mehr aufgerufen */
    }
    


  • Fake oder Echt schrieb:

    Gehen wir davon aus wir haben einen Gültigkeitsbereich, in dem ein Stream geöffnet wird. Irgendwo zwischendrin schmiert das Programm ab, ohne eine Exception zu werfen. Die Dateioperationen sind längst abgeschloßen. Was ist die Folge: Destruktor wird nicht aufgerufen, Datei wird nicht geschloßen, lässt sich vom User nicht mehr bearbeiten/verschieben/löschen weil Windoof sagt "Datei in Verwendung". Warum dann kein close () verwenden um sowas zu vermeiden? Oder sehe ich da was Falsch?

    Wenn das Programm abstürzt (!= es wird eine Exception geworfen), dann liegt es im Tätigkeitsbereich des Betriebssystems alle Resourcen freizugeben. Du kannst an der Stelle nichts mehr machen. Im Grunde verlagerst du das Problem nur an einen anderen Ort. Der Code der vorher durch ctor/dtor eingerahmt wurde wird jetzt durch ctor/close() oder open()/close() eingerahmt. Macht keinen Unterschied. Natürlich solltest du trotzdem darauf achten, dass du Resourcen nicht zu lange verwendest. Aber das erreichst du durch modularisierung einfacher, als durch das willkürliche Einstreuen von close().

    Mal dein Beispiel weiter kommentiert:

    { // Gültigkeitsbereich
        ifstream bla ("datei.txt");
    
        /* Mache hier alle gewünschten Operationen mit der Datei */
    
        /* Hier könnte jetzt ein bla.close () rein, weil alle Dateioperationen erledigt wurden */
        //das war ein deutlicher Gedanke, dass hier eine Bedeutungseinheit zuende ist, also ist alles was drüber kommt, eine Funktion
    
        /* Hier schmiert das Programm ab, ohne Exception, d.h. Destruktor für bla wird nicht mehr aufgerufen */
    }
    

    =>

    SomeType readFile(){
        ifstream bla ("datei.txt");
        /* Mache hier alle gewünschten Operationen mit der Datei */
    
        /* lass den Destruktor aufräumen*/
    }
    
    { // Gültigkeitsbereich
        SomeType type = readFile();
    
        /* Hier schmiert das Programm ab, ohne Exception, aber bla ist bereits kaputt, awesome!*/
    }
    


  • Skotchy schrieb:

    Vor der nächsten Aufgabe hätte ich da nochmal eine Frage.
    Dieses Auslesen einer Datei kann man doch (auch) dazu benutzen um Spielstände zu laden, richtig? Dann müsste man für das Speicher die Datei einfach ändern bzw. neu beschreiben, oder?

    Ja, natürlich geht das. Du musst dir halt ein Format für die Spielstände überlegen in dem alle wichtigen Informationen abgespeichert werden (Punkte, Fortschritt, ...) und die schreibst du dann in eine Datei und kannst sie später wieder auslesen.

    Das spezielle Beispiel mit der std::map hier könnte man für Werte und ähnliches sogar direkt benutzen, auch wenn der Zusammenhang eigentlich gar nicht geplant war. 🙂



  • cooky451 schrieb:

    auch wenn der Zusammenhang eigentlich gar nicht geplant war. 🙂

    ist doch supper, dann hab ich also indirekt mehr gelernt als vorgesehen war. 🙂

    cooky451 schrieb:

    Du musst dir halt ein Format für die Spielstände überlegen in dem alle wichtigen Informationen abgespeichert werden (Punkte, Fortschritt, ...) und die schreibst du dann in eine Datei und kannst sie später wieder auslesen.

    wird zwar noch ein bisschen früh sein aber welche Formate empfehlen sich da besonders gut, oder gibt es da je nach Spiel andere die sich besser eignen?

    Jetzt freue ich mich aber auf die nächste Aufgabe(und natürlich wieder, falls vorhanden, auf den 'versteckten' unbeabsichtigten Inhalt 😉 ).

    Weiterhin danke für eure Hilfe.

    -Skotchy



  • otze schrieb:

    SomeType readFile(){
        ifstream bla ("datei.txt");
        /* Mache hier alle gewünschten Operationen mit der Datei */
        
        /* lass den Destruktor aufräumen*/
    }
    
    { // Gültigkeitsbereich
        SomeType type = readFile();
    
        /* Hier schmiert das Programm ab, ohne Exception, aber bla ist bereits kaputt, awesome!*/
    }
    

    Ja gut, dass da da bereits aufgeräumt wurde ist ja klar, da ja der Gültigkeitsbereich von bla nur innerhalb von readFile () liegt. Mein Gedanke war nur, Handle wird in dem entsprechenden Bereich nicht geschloßen, also geht Windoof davon aus, dass die Datei nicht beendet wurde, aber du hast ja erklärt, dass dieses Problem von offenen unbenutzten Handles nach dem Programmabsturz an das OS weitergegeben wird bzw. bearbeitet werden soll, also is meine Frage geklärt, danke 🙂



  • Skotchy schrieb:

    wird zwar noch ein bisschen früh sein aber welche Formate empfehlen sich da besonders gut, oder gibt es da je nach Spiel andere die sich besser eignen?

    Mit denk dir ein Format aus war genau das gemeint, denk dir ein Format aus. Für so etwas gibt es keinen Standard (wehe jetzt kommt mir einer mit xml. ;)).
    Das kommt ganz auf das Spiel an, welches du machen möchtest. Nehmen wir ein Jump&Run Spiel. Da würde man nur die Punkte / das aktuelle Level speichern. Bei einem Rollenspiel sieht das ganz anders aus, da kommen so Sachen wie Inventar, Attribute, etc. pp. dazu.

    Skotchy schrieb:

    Jetzt freue ich mich aber auf die nächste Aufgabe(und natürlich wieder, falls vorhanden, auf den 'versteckten' unbeabsichtigten Inhalt 😉 ).

    Kleine Übung zu Iteratoren. Implementiere std::sort , allerdings nur mit Bubblesort. (Kannst natürlich auch Quicksort oder so nehmen, aber es soll ja um die Sprache und nicht um den Algorithmus gehen.)

    Als Beispiel für den generellen Umgang mit Iteratoren siehe: http://www.cplusplus.com/reference/algorithm/ .
    Sehr viele dieser Algorithmen sind sehr einfach und haben dort eine Beispielimplementierung.



  • Ok, ich glaube ich habe die Aufgabe verstanden aber in meinem Code einen (kleinen?!) Denkfehler.

    #include <iostream>
    #include <algorithm>
    
    int main()
    {
    	int Zahlen[] = {13,63,4,85,23,1,51,6790,6,2}, maenge = 10;
    
    	bool Unsortiert = false;
    	while ( !Unsortiert && maenge > 1)
    	{
    		for (int i; i > i +1; i++)
    		{
    			if (Zahlen[i] > Zahlen[++i])
    			{
    				std::sort(Zahlen[i - 1], Zahlen[++i - 1]);
    				Unsortiert = true;
    			}
    		}
    		maenge -= 1;
    	}
    
    	for(int i = 0; i >= 0; i++)
    		std::cout << Zahlen[i] << ", ";
    }
    

    Der Compiler sagt mir, dass da irgendetwas Falsch ist aber markiert nichts als Fehler 😮 .
    Ist da eventuell etwas defekt oder ist das normal so?

    Weiterhin danke für eure Hilfe.

    -Skotchy



  • Du hast weder std::sort noch die Aufgabenstellung verstanden. Um das noch mal zu betonen: Du sollst die Funktion std::sort nachbauen. Angewendet wird std::sort so:

    #include <algorithm>
    #include <vector>
    
    int main()
    {
      std::vector<int> v;
      v.push_back(5);
      v.push_back(3);
      v.push_back(76);
      v.push_back(9);
      // ...
      std::sort(v.begin(), v.end());
      // Jetzt ist der Vektor sortiert, aus, ende. Nichts mit while (unsorted) ...
    }
    


  • Skotchy schrieb:

    Der Compiler sagt mir, dass da irgendetwas Falsch ist [...]

    ... und was Dein Compiler sagt, erfahren wir sicher durch unsere Kristallkugeln.



  • Du könntest dir auch einfach mal die Anwendungsbeispiele zu std::sort durchlesen:
    http://www.cplusplus.com/reference/algorithm/sort/
    Das ist eigentlich immer der erste Schritt, wenn man Funktionen nicht kennt.



  • So, hat zwar etwas länger gedauert aber ich wollte die Aufgabe erst versuchen zu verstehen. Ich soll std::sort nicht anwenden sondern nachbauen, dabei soll ich das 'Bibblesort-Prinzip' anwenden also die Zahlen immer wieder durchgehen und nur zwei nebeneinander liegende Zahlen miteinander vertauschen wenn sie nicht in der richtigen Reihenfolge stehen. Wenn ich das nicht machen sollte habe ich die Aufgabe leider immer noch nicht verstanden.
    Und hier ist mein Programm, allerdings immer noch mit Fehlern:

    #include <iostream>
    #include <algorithm>
    #include <vector>
    
    void tausch(std::vector<int> &x, std::vector<int> &y)
    {
    	std::vector<int> ablage;
    	ablage = x;
    	x = y;
    	y = ablage;
    }
    
    int main()
    {
    	int zahlen[] = {4, 71, 74, 24, 97, 3, 388, 622, 2};
    	std::vector<int> Zahlen (zahlen, zahlen + 9);
    
    	for (std::vector<int>::iterator i = Zahlen.begin(); i != Zahlen.end(); ++i)
    	{
    		if (Zahlen[i] > Zahlen[++i])
    			tausch(Zahlen[i], Zahlen[++i]);
    	}
    
    	for (int i = 0; i != Zahlen.size(); ++i)
    		std::cout << Zahlen[i] << " ";
    }
    

    Die Fehler liegen in der for-Schleife bei 'Zahlen[i]' und ich weiß nicht wie ich den Fehler korrigieren könnte.

    Weiterhin danke für eure Hilfe.

    -Skotchy


  • Mod

    Skotchy schrieb:

    Die Fehler liegen in der for-Schleife bei 'Zahlen[i]' und ich weiß nicht wie ich den Fehler korrigieren könnte.

    du kannst den fehler korrigieren indem du rausfindest was "++i" bedeutet.



  • rapso schrieb:

    Skotchy schrieb:

    Die Fehler liegen in der for-Schleife bei 'Zahlen[i]' und ich weiß nicht wie ich den Fehler korrigieren könnte.

    du kannst den fehler korrigieren indem du rausfindest was "++i" bedeutet.

    Bedeutet das nicht einfach 'i + 1'?


  • Mod

    Skotchy schrieb:

    rapso schrieb:

    Skotchy schrieb:

    Die Fehler liegen in der for-Schleife bei 'Zahlen[i]' und ich weiß nicht wie ich den Fehler korrigieren könnte.

    du kannst den fehler korrigieren indem du rausfindest was "++i" bedeutet.

    Bedeutet das nicht einfach 'i + 1'?

    wuerde dann diese zeile einen sinn ergeben?

    for (std::vector<int>::iterator i = Zahlen.begin(); i != Zahlen.end(); ++i)

    ?
    schau es nach, es lohnt sich 😉



  • Ok, ich hab es jetzt nochmal nachgeguckt. Das '++' vor dem 'i' erhöht es um eins. Also habe ich das 'i' in der for-Schleife pro Durchlauf drei mal erhöht. Aber ich kann den Fehler weiterhin nicht beheben. Ich bekomme immer die '[' rot unterstrichen. Nur wenn ich eine Zahl für das 'i' eingebe verschwindet die Unterstreichung, aber warum nicht bei 'i'?

    Weiterhin danke für eure Hilfe.

    -Skotchy



  • Guck dir Iteratoren noch mal an. Und denk daran, du sollst eine Funktion schreiben und nicht alles in die main packen. 😉



  • Das Programm funktioniert so halb weil es es meine Zahlen nicht sortiert.

    #include <iostream>
    #include <algorithm>
    #include <vector>
    
    void tausch(int x, int y)
    {
    	int ablage;
    	ablage = x;
    	x = y;
    	y = ablage;
    }
    
    void sortieren(std::vector<int>Zahlen)
    {
    	for (std::vector<int>::iterator i = Zahlen.begin(); i != Zahlen.end();i++)
    	{
    		if (*i > *i+1)
    			tausch (*i, *i+1);
    
    	}
    	for (int i = 0; i != Zahlen.size(); i++)
    		std::cout << Zahlen[i] << " ";
    }
    
    int main()
    {
    	int zahlen[] = {4, 71, 74, 24, 97, 3, 388, 622, 2};
    	std::vector<int> Zahlen (zahlen, zahlen + 9);
    
    	sortieren(Zahlen);
    }
    

    Ich haffe das da nicht so viele Fehler drin sind.

    Weiterhin danke für eure Hilfe.

    -Skotchy



  • und du glaubst, ein zeilendurchlauf reicht? stell dir mal vor, du musst das hinterste Element ganz nach vorne packen. Funktioniert das so?



  • Das sieht doch schon mal viel besser aus, als die letzten Versuche. Eine eigene Swap Funktion brauchst du übrigens gar nicht, std::swap kannst du gerne verwenden.

    (In Zeile 13 fehlt übrigens ein Leerzeichen, lustig, dass das so überhaupt kompiliert.)

    Zum Algorithmus: Du kannst den Pseudocode der deutschen Wikipedia eigentlich 1:1 übertragen, guck dir den noch mal an. Und wenn es dann läuft, vergiss nicht, dass du std::sort nachbilden sollst. Der Funktionsprototyp sieht so aus:

    template<class RandomAccessIterator>
    void sort(RandomAccessIterator first, RandomAccessIterator last);
    // Den zweiten Fall mit dem nicht-Standard Vergleich lassen wir mal weg.
    

Anmelden zum Antworten