Konsolenspiel - Snake Race(v2.0)



  • Ich habe mal kurz über den neuen Sourcecode geschaut (naja, über einen Teil zumindest 😉 ).
    Erst mal Kompliment, das sieht schon viel aufgeräumter auf.

    2 Dinge fallen trotzdem auf. Du hast jetzt eine Klasse geschrieben für dein Spiel. Im Moment ist das aber vom Prinzip her eher eine Struktur mit ein paar Hilfsfunktionen. Du hast für _jede_ Variable eine get und set funktion, die nichts anderes machen als den Wert der Variable ohne überprüfung zu setzen bzw. zurückzugeben.
    So könntest du ja gerade so gut alle Variablen public machen und hättest dir eine Menge Schreibarbeit gespart.

    Ein Beispiel was z.B. verändert werden könnte.

    drei.set_points(drei.get_points()+1);
                gotoxy(13, 55);
                cout << drei.get_points() << " von 15 Punkten";
    

    Immer wenn du die Punkte veränderst willst du auch die Punkteanzeige am Bildschirm updaten. Lass das doch deine Klasse (bzw. die set Funktion) machen. Die Set Funktion würde dann immer wenn die Punkte geändert werden, diese auch an die entsprechende Position am Bildschirm schreiben. So weisst du dass die Anzeige immer mit der Punktzahl übereinstimmt.
    Evt. sollte die set Funktion sogar noch mehr machen, z.B. überprüfen ob du schon gewonnen hast. Wenn ja kannst du ja true zurückgeben sonst false.
    Ausserdem bietet es sich auch an eine erhoehe_Punkte Funktion zu schreiben, wenn du öfters so etwas wie oben machst.
    Oder

    zwei.setze_richtung(c);
            } //if(kbhit())
    
            if(!zwei.get_x_plus()  && !zwei.get_y_plus()
            && !zwei.get_x_minus() && !zwei.get_y_minus()) continue;
    

    wie wäre es, wenn setze_richtung die überprüfung gleich durchführt und das Ergebnis zurückliefert?
    Das gilt nicht nur für die Spiel Klasse sondern für alle, das zieht sich durch den ganzen Code... z.B. auch wenn du den Spieler auf ein Feld setzt machst du jede Menge abfragen (ist da ein Brunnen? Spieler nicht zeichnen. Ist da eine Wand? Spieler vor der Wand zeichnen. etc.). Wäre es nicht einfacher, wenn du eine Funktion hättest die all das erledigt sobald du die Position des Spielers änderst (und dann halt zurückgibt, ob er noch lebt).

    Zweiter Punkt: Deine modus1, modus2, modus3, etc. files sind fast identisch. Da brauchst du eigentlich nur eine Funktion, bei dem du das Spiel je nach Modus mit unterschiedlichen Start / Gewinn Werten initialisierst.



  • Ich find das Spiel gut! Sourcecode hab ich nur überflogen. Auslachen lassen musst Du dich deswegen keinesfalls!

    Tipps/Anmerkungen/Prinzipienreiterei:

    • Verwende enums (z.B.: rest.h, "farben für die color-funktion")
    • Vermeide Wiederholungen (Ja, damit wiederhole ich nur, was mein Vorredner schon sagte^^)
    • in den einzelnen Modus-Funktionen setzt Du jeweils den random-seed. Mach das doch einmal ganz vorne in main(), dann brauchst Du das im ganzen Programm nicht wieder.
    • Das zusammenstückeln der Strings wie z.B. in rest::hilfe_modus ist unästhetisch und macht den Code nicht lesbarer. Ich glaube, derartige Optimierung ist in einem solchen Programm an dieser Stelle etwas übertrieben.
    • Bei den get/set-Funktionen kann ich meinem Vorredner nur zustimmen.
    • Es wäre gut, wenn Du deinen Einrückstil etwas konsequenter befolgen würdest - das macht den Code lesbarer
    • using namespace std; ist zwar eine Tipperleichterung, aber es hat einen Grund, dass die Funktionen in einen namespace gelegt wurden: Diesen nun in den global namespace auszukippen macht den Vorteil zunichte, dass man bei der Benennung eigener Variablen/Funktionen nicht darum scheren muss, ob es vielleicht eine gleichnamige Funktion in der Standardbibliothek gibt. -> Ich weiß, es ist mühsam, immer std:: davor zu schreiben, aber ich würds mir angewöhnen.
    • int main() fehlt das return 0; am Ende. Ja, (leider) muss man es nichtmehr schreiben, aber ich finds inkonsequent, es wegzulassen.

    mfg
    Mr X



  • Hm das mit den Überprüfungen in den get/set Methoden scheint sinnfoll, das werde ich wohl machen. Gute Idee^^

    Ja, eine Funktion die das ganze zeichnet und überprüft ob er noch lebt, bzw. wie er gestorben ist, wäre auch nicht schlecht.

    Zu den verschiedenen Modi:
    Es sind ja nicht nur die Anzahl der Objekte und die Geschwindigkeit die sich unterscheiden. Die Schrittbegrenzung ist anders und in Modus 3 und 4 gar nicht erst vorhanden, die maximale Punktzahl ist anders, bei Modus 4 wird beim verlieren immer der Name abgefragt, bei Modus 1, 2, und 3 nicht, im vierten Modus gibt's ab 20 Punkten noch extra-Objekte, bei jedem Modus-Start wird ein anderer text animiert und andere Farben verwendet uvm.
    Es wäre ziemlich schwierig, eine Funktion zu schreiben, die dann jedes mal überprüfen müsste, welcher Modus gemeint ist (Ist es der vierte? Keine Schrittbgrenzung, kein Punktelimit, Text animieren usw., ist es der zweite? Schrittlimit 800, kein Punktelimmit, den Text animieren usw.).
    Das sind eben alles Kleinigkeiten die in den Modi anders sind.

    Okay, enums könnte ich verwenden, gute Idee.
    Und stimmt, srand() vorzubereiten brauche ich nur einmal. Das mir das nicht aufgefallen ist o.o
    Echt nicht? es sind nämlich nur 2 Wörter die sich unterscheiden, sodass es mir sinnfoll schien, einfach zu überprüfen welcher Modus übergeben wurde.
    Ja, ich bin zwischendurch auf 2 Leerzeichen pro Tab umgestiegen, da hast du recht.
    Das stört mich allerdings schon mit using namespace std;
    Denn bei einem Quellcode mit knapp 500 Zeilen (was ja noch sehr wenig ist) über 100 mal std:: schreiben zu müssen, nur damit ich ein paar Funktionsnamen und Variablennamen selbst definieren kann, scheint mir eigentlich unsinnig. Außerdem, wenn etwas mal schon in std steht, dann mache ich halt den Anfangsbuchstaben groß o.ä. Und außerdem gilt using namespace std; ja nur für die aktuelle Datei.
    Und zu return 0; -> wenn main sowieso 0 zurückgibt wenn mans nicht angibt, wozu sollte ichs dann angeben? 😉

    Also danke für die Tipps, da sind einige wirklich gut bei 🙂



  • Incocnito schrieb:

    Hm das mit den Überprüfungen in den get/set Methoden scheint sinnfoll, das werde ich wohl machen. Gute Idee^^

    Ja, eine Funktion die das ganze zeichnet und überprüft ob er noch lebt, bzw. wie er gestorben ist, wäre auch nicht schlecht.

    Zu den verschiedenen Modi:
    Es sind ja nicht nur die Anzahl der Objekte und die Geschwindigkeit die sich unterscheiden. Die Schrittbegrenzung ist anders und in Modus 3 und 4 gar nicht erst vorhanden, die maximale Punktzahl ist anders, bei Modus 4 wird beim verlieren immer der Name abgefragt, bei Modus 1, 2, und 3 nicht, im vierten Modus gibt's ab 20 Punkten noch extra-Objekte, bei jedem Modus-Start wird ein anderer text animiert und andere Farben verwendet uvm.
    Es wäre ziemlich schwierig, eine Funktion zu schreiben, die dann jedes mal überprüfen müsste, welcher Modus gemeint ist (Ist es der vierte? Keine Schrittbgrenzung, kein Punktelimit, Text animieren usw., ist es der zweite? Schrittlimit 800, kein Punktelimmit, den Text animieren usw.).
    Das sind eben alles Kleinigkeiten die in den Modi anders sind.

    Okay, enums könnte ich verwenden, gute Idee.
    Und stimmt, srand() vorzubereiten brauche ich nur einmal. Das mir das nicht aufgefallen ist o.o
    Echt nicht? es sind nämlich nur 2 Wörter die sich unterscheiden, sodass es mir sinnfoll schien, einfach zu überprüfen welcher Modus übergeben wurde.
    Ja, ich bin zwischendurch auf 2 Leerzeichen pro Tab umgestiegen, da hast du recht.
    Das stört mich allerdings schon mit using namespace std;
    Denn bei einem Quellcode mit knapp 500 Zeilen (was ja noch sehr wenig ist) über 100 mal std:: schreiben zu müssen, nur damit ich ein paar Funktionsnamen und Variablennamen selbst definieren kann, scheint mir eigentlich unsinnig. Außerdem, wenn etwas mal schon in std steht, dann mache ich halt den Anfangsbuchstaben groß o.ä. Und außerdem gilt using namespace std; ja nur für die aktuelle Datei.
    Und zu return 0; -> wenn main sowieso 0 zurückgibt wenn mans nicht angibt, wozu sollte ichs dann angeben? 😉

    Also danke für die Tipps, da sind einige wirklich gut bei 🙂

    Sorry, konnte einfach nicht widerstehen ^^



  • Hä?

    EDIT: Boa, nach über einem Monat seh ich gerade das mir ein rechtschreib-super-gau gelungen ist. Ufff..



  • So, ich hab jetzt Version 2.0 fertig. Änderungen sind (unter anderem):

    -Fenster vergrössert
    -Schwierigkeit wird nun angegeben
    -einzelne Modi verändert/verbessert
    -Items angepasst (auch an die modi)

    Für detailliertere Informationen siehe Einblendung beim ersten Spielstart oder Versions.log.

    Da ich es jetzt endlich geschafft habe, das Fenster der Konsole unter dem GCC zu vergrößern, kann man endlich mal alles erkennen 😉
    Das hat aber leider ein ziemlich unschönes copy & paste Chaos in der main.cpp verursacht. Naja, was will man machen..

    Ich hab den Code nochmal leicht überarbeitet und das 100-mal (exakt) vorkommende std:: gelöscht und überall using namespace std; geschrieben, gegen den Hinweis von Mr X. Den Grund habe ich ja bereits genannt..
    Außerdem hab ich die Farben in eine enum gesteckt.

    Viel Spaß 😉



  • Die massenweisen überflüssigen get/set-Methoden gibts immernoch...

    Und außerdem gilt using namespace std; ja nur für die aktuelle Datei.

    Das ist blödsinn, wenn Du es in Header schreibst (Was Du ja auch getan hast). Dann gilt es nämlich für jede .cpp-Datei, die diesen Header includiert genauso.



  • Naja es ist jetzt halt schwierig das alles mit den vielen einzeln vorkommenden get/set-methoden umzuschreiben. Für vergleichsweise wenig Gegenleistung. Beim nächsten mal werde ich eben darauf achten, aber das jetzt alles nochmal umzutippen (es sollte ja auch eigentlich eine struktur sein) wär viel zu mühselig.



  • Ich hatte Langeweile und hab sie dann doch noch umgeändert. Das ganze hab ich dann hier hochgeladen. Eine Funktion punkte_erhoehen hab ich nicht geschrieben, da jetzt durch die neuen Items manchmal auch 2 mal die Punkte erhoeht werden, schien mir so leichter. Sonst hab ich eigentlich alle eure Tipps befolgt, außer das mit using namespace std. Ist das jetzt besser geworden oder hab ich es nun verschlimmbessert? 😃 Die Überprüfungen und Ausgaben geschehen nun in den set-Methoden und ich hab einige gelöscht bzw. umbenannt und geändert. Die Datentypen hab ich teilweise angepasst und ein paar Member gelöscht (pausiert, durch, etc.). Danke für die Hilfe ^^



  • Hast du eig. ICQ oder Skype?



  • Klar, einfach auf mein Profil klicken. Da steht meine ICQ drin.


Anmelden zum Antworten