Erstes Programm - Verbesserungsvorschläge?



  • Hey Leute,

    ich habe mich die letzte Zeit mit C++ auseinandergesetzt, und auch mein erstes (richtiges) "Spiel" (falls man das so nennen kann) programmiert.
    Ich kann mir aber selbst denken, dass der Code nicht perfekt ist, und möchte daher Tipps einholen, um meinen Stil zu verbessern, und mir auch Dinge anzueignen.

    Der Code:

    #include <iostream>
    #include <Windows.h>
    #include <conio.h>
    #include <ctime>
    #include <cstdlib>
    #include <string>
    
    using namespace std;
    
    int main() {
    
    	while (true) {
    
    		bool win = true;
    
    		//Variablen
    		char choice;
    		string letter;
    		string letterpruef;
    		int amount;
    		int a;
    		int apr = 100;
    		int b;
    		int bpr = 100;
    		int c = 32;
    		int cpr = 100;
    		int j;
    		int x;
    		int y;
    		int durch = 0;
    		int punkte = 0;
    		int zeit;
    		int timer;
    		string userInp;
    
    		string court[10][10] = {
    			{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
    			{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
    			{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
    			{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
    			{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
    			{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
    			{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
    			{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
    			{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
    			{ " ", " ", " ", " ", " ", " ", " ", " ", " ", " " },
    		};
    
    		string index[26] = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
    		char pruef[27] = "abcdefghijklmnopqrstuvwxyz";
    
    		string load[9] = { "#","#","#","#","#","#","#","#","#" };
    
    		//Hauptmenü
    		do {
    
    			system("CLS");
    
    			cout << "Willkommen beim Tastendruck-Reaktionsspiel!" << endl << endl;
    			cout << "Du wirst auf dem Bildschirm verschiedene Buchstaben aufleuchten" << endl;
    			cout << "sehen. Deine Aufgabe ist es die entsprechende Taste zu druecken" << endl << endl;
    			cout << "Viel Spass! Druecke 'S' um zu beginnen!";
    
    			choice = getch();
    
    		} while (choice != 's');
    
    		//Einstellungen
    
    		do {
    			system("CLS");
    
    			cout << "Wie viele Buchstaben willst du angezeigt bekommen?" << endl << endl;
    			cin >> amount;
    		} while (amount <= 0);
    
    		//Spiel
    
    		zeit = time(NULL);
    
    		for (j = 0; j <= amount; j++) {
    			system("CLS");
    
    			do {
    				durch = 0;
    
    				srand(time(NULL));
    				a = rand() % 26;
    
    				durch++;
    
    			} while (a == apr || durch == 100);
    
    			letter = index[a];
    			letterpruef = pruef[a];
    			apr = a;
    
    			do {
    				durch = 0;
    
    				srand(time(NULL));
    				b = rand() % 9;
    
    				durch++;
    
    			} while (b == bpr || durch == 100);
    
    			bpr = b;
    
    			do {
    				durch = 0;
    
    				srand(time(NULL));
    				c = rand() % 9;
    
    				durch++;
    
    			} while (c == cpr || durch == 100);
    
    			cpr = c;
    			court[b][c] = letter;
    
    			for (x = 0; x < 10; x++) {
    				for (y = 0; y < 10; y++) {
    					if (court[x][y] != " " && x != b && y != c) {
    						court[x][y] = " ";
    					}
    				}
    			}
    
    			for (x = 0; x < 10; x++) {
    				for (y = 0; y < 10; y++) {
    					if (y == 9) {
    						cout << court[x][y] << endl;
    					}
    					else {
    						cout << court[x][y];
    					}
    				}
    			}
    
    			timer = time(NULL) + 6;
    
    			if (j <= 5) {
    				timer = timer - j;
    			}
    			else if (j > 5) {
    				timer = timer - 5;
    			}
    
    			//cout << timer - time(NULL) << endl;
    
    			while (time(NULL) != timer)
    			{
    				// cout << time(NULL) << " & " << timer << endl;
    
    				if (kbhit()) // Nur wenn auch eine Taste gedrückt ist 
    				{
    
    					char c = getch(); // Muss auf keine Eingabe warten, Taste ist bereits gedrückt 
    
    					if (c = pruef[a]) {
    						punkte++;
    
    						break;
    
    					}
    				}
    
    			}
    
    		}
    
    		zeit = time(NULL) - zeit;
    
    		system("CLS");
    		cout << "Du hast eben " << punkte << " von " << amount << " Punkten erreicht!" << endl;
    		cout << "Deine Zeit betrug " << zeit << " Sekunden!" << endl;
    		getch();
    
    	}
    
    	return (0);
    
    	// time_t sekunden = time(NULL);
    }
    

    In dem Spiel geht es lediglich darum Tasten zu drücken, welche wahllos auf dem Bildschirm (Naja, in einem 10x10 Array) erscheinen. Mit der Zeit sinkt die Zeitspanne, wie lange ein Buchstabe auf dem Bildschirm angezeigt wird. Da habe ich auch ein Problem zu bemängeln: am ende ist die Zeitspanne eine Sekunde, und sie sinkt von da auch nicht mehr. Nun werden allerdings manchmal die Buchstaben so wie die Position im Array zu langsam errechnet. Wäre also toll wenn ich da einen guten Tipp bekäme 🙂

    Vielen Dank schonmal im Voraus!

    EDIT: Das langsame rechnen kam vom Debuggen. Hab das Programm einmal im Release Modus ausgeführt und die Ladezeiten waren verschwunden. ^^

    Edit^2 durch Arcoth: Bitte Code nicht verlinken sondern unmittelbar im Post beinhalten.



  • Ein Punkt der mir spontan beim drüberschauen auffällt: das komplette Programm besteht aus 180 Zeilen in der main Funktion. Das könnte man sicher in kleinere Funktionen aufspalten.


  • Mod

    Ist leider von Anfang an abschreckend unlesbar:

    bool win = true;
    
            //Variablen
            char choice;
            string letter;
            string letterpruef;
            int amount;
            int a;
            int apr = 100;
            int b;
            int bpr = 100;
            int c = 32;
            int cpr = 100;
            int j;
            int x;
            int y;
            int durch = 0;
            int punkte = 0;
            int zeit;
            int timer;
            string userInp;
    

    Führ Variablen dort ein, wo sie gebraucht werden, nicht alle auf einem Haufen am Anfang. Gib ihnen aussagekräftige Namen, nicht bloß einen einzelnen Buchstaben oder eine kryptische Abkürzung als Bezeichner. Benutze einheitlich eine einzelne Sprache, vorzugsweise Englisch. Guter Code sollte sich lesen lassen wie ein Gedicht¹, dein Programm ist leider das absolute Gegenteil.

    Ansonsten schaut das ganz ordentlich aus für ein erstes Programm. Es sollte dir aber klar sein, dass man später nicht in diesem Stil programmiert. Bei dir ist derzeit alles mit allem fest verwoben. Normalerweise versucht man aber im Gegenteil möglichst weit unabhängige Komponenten zu identifizieren und diese dann auch vollkommen unabhängig voneinander umzusetzen. Dann gibt es nur ein paar kleine Stellen im Programm, die das Wechselspiel dieser Komponenten bestimmen. Diese Vorgehensweise hat wesentliche Vorteile bei der Entwicklung von komplexen und trotzdem fehlerfreien Programmen.

    Ich habe das Programm nicht auf technische Fehler geprüft, da ich es bei mir wegen der Windowsabhängigkeiten nicht übersetzen kann.

    ¹: Das ist auch einer der Gründe, warum englische Bezeichner hilfreich sind: Da die Schlüsselwörter bereits auf Englisch sind, hat man dann eine einheitliche Sprache für das Gedicht.



  • Beim drüber fliegen. Das da ist unnötig.

    string index[26] = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
    

    Es geht etwas eleganter:

    char letterB = 'A' + 1; // B
    char letterC = 'A' + 2; // C
    

  • Mod

    jb schrieb:

    Beim drüber fliegen. Das da ist unnötig.

    string index[26] = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
    

    Es geht etwas eleganter:

    char letterB = 'A' + 1; // B
    char letterC = 'A' + 2; // C
    

    Würde ich nicht unbedingt als Schwäche auslegen (außer dass hier offensichtlich chars, keine strings gemeint sind), denn:
    1. Bei strenger Standardauslegung muss die genannte Beziehung nicht gelten (wird sie aber fast sicher).
    2. Viel wichtiger: So kann man den Zeichensatz später einfacher verändern.



  • SeppJ schrieb:

    Würde ich nicht unbedingt als Schwäche auslegen (außer dass hier offensichtlich chars, keine strings gemeint sind)

    Ich sehe es nicht als Schwäche, wollte nur sagen, dass es einfacher geht. Er verwendet zwar strings, die sind aber immer genau ein Zeichen lang (außer ich hab was übersehen) und daher wäre der Datentyp char doch besser - oder nicht?

    SeppJ schrieb:

    1. Bei strenger Standardauslegung muss die genannte Beziehung nicht gelten (wird sie aber fast sicher).

    Gibt es Fälle wo die ASCII Tabelle hinfällig wird, wann?

    SeppJ schrieb:

    2. Viel wichtiger: So kann man den Zeichensatz später einfacher verändern.

    Wie verändert man den Zeichensatz? (Quellcode-Datei in ein anderes Format konvertieren?) Hast Du ein Beispiel, wann ich gezielt den Zeichensatz ändern möchte?



  • jb schrieb:

    SeppJ schrieb:

    1. Bei strenger Standardauslegung muss die genannte Beziehung nicht gelten (wird sie aber fast sicher).

    Gibt es Fälle wo die ASCII Tabelle hinfällig wird, wann?

    Naja, wenn halt kein ASCII benutzt wird, sondern irgendwas anderes. EBCDIC oder so.



  • Das mit dem String kommt von daher dass ich anfangs einen Fehler mit Char-Arrays gemacht habe. Ich habe eben versucht alle Buchstaben in Anführungszeichen zu stecken, was mir allerdings einen Fehler ausgab. Habe mich nun noch einmal dazu belesen und rausgefunden wie ein Char-Array funktioniert.

    Danke auch schon führ die ganzen Tipps 😉



  • D4RKS0UL23 schrieb:

    Habe mich nun noch einmal dazu belesen und rausgefunden wie ein Char-Array funktioniert.

    Kann er dann nicht gleich seine char-Arrays so füllen?

    std::string index, pruef; //strings sind eigentlich char-Arrays
        char letter, letterpruef;
    
        for (int i=0; i<26; i++) //Anzahl Buchstaben vom Alphabet
        {
            index.push_back(char(65+i)); //füllen ab 'A'
            pruef.push_back(char(97+i)); //füllen ab 'a'
    
        }
    
      letter = index.at(a);
      letterpruef = pruef.at(a);
    

    (uh, 5-mal bearbeitet :D)



  • lemon03 schrieb:

    D4RKS0UL23 schrieb:

    Habe mich nun noch einmal dazu belesen und rausgefunden wie ein Char-Array funktioniert.

    Kann er dann nicht gleich seine char-Arrays so füllen?

    std::string index, pruef; //strings sind eigentlich char-Arrays
        char letter, letterpruef;
    
        for (int i=0; i<26; i++) //Anzahl Buchstaben vom Alphabet
        {
            index.push_back(char(65+i)); //füllen ab 'A'
            pruef.push_back(char(97+i)); //füllen ab 'a'
    
        }
    
      letter = index.at(a);
      letterpruef = pruef.at(a);
    

    (uh, 5-mal bearbeitet :D)

    Naja ein char array sah bei mir immer so:

    char var [27] = "abcdefghijklmnopqrstuvwxyz"
    

    Es sind aus irgendeinem grund 27 Zeichen (Das 27. zeichen ist ein sehr komisches)


  • Mod

    jb schrieb:

    Wie verändert man den Zeichensatz? (Quellcode-Datei in ein anderes Format konvertieren?) Hast Du ein Beispiel, wann ich gezielt den Zeichensatz ändern möchte?

    Ich bezog mich auf den Zeichensatz, den das hier gezeigte Programm unterstützt. Vielleicht möchte der Autor später auch mal Ziffern und Sonderzeichen als Elemente des Spiels haben.

    D4RKS0UL23 schrieb:

    Naja ein char array sah bei mir immer so:

    char var [27] = "abcdefghijklmnopqrstuvwxyz"
    

    Es sind aus irgendeinem grund 27 Zeichen (Das 27. zeichen ist ein sehr komisches)

    Das letzte Zeichen ist ein verstecktes Nullzeichen. Das hat etwas mit den historischen Wurzeln von C++ zu tun. Genauer damit, wie in der Sprache C Zeichenketten behandelt werden. Kann hier einfach ignoriert werden. Falls es dich interessiert (und es kann in Fällen wie hier schließlich auch in C++ mal relevant werden):
    https://en.wikipedia.org/wiki/Null-terminated_string



  • D4RKS0UL23 schrieb:

    Naja ein char array sah bei mir immer so:

    char var [27] = "abcdefghijklmnopqrstuvwxyz"
    

    Es sind aus irgendeinem grund 27 Zeichen (Das 27. zeichen ist ein sehr komisches)

    Dann würde ich es aber wenigstens so

    std::string var = "abcdefghijklmnopqrstuvwxyz";
    

    schreiben.

    Oder gibt es hier einen speziellen Grund für char[], den ich gerade nicht sehe?


  • Mod

    lemon03 schrieb:

    Oder gibt es hier einen speziellen Grund für char[], den ich gerade nicht sehe?

    Umgekehrt: Gibt es einen speziellen Grund für string ? Wenn nicht, warum dynamische Speicherallokation?



  • Mmh ... gute Frage 😉

    Wenn ich albern wäre, würde ich jetzt antworten, weil es moderner aussieht 😃 Aber sonst hätte ich jetzt keine Begründung ...



  • jb schrieb:

    Beim drüber fliegen. Das da ist unnötig.

    string index[26] = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
    

    Es geht etwas eleganter:

    char letterB = 'A' + 1; // B
    char letterC = 'A' + 2; // C
    

    __jb__ schreibt Unfug wiedermal. 💡



  • volkard schrieb:

    __jb__ schreibt Unfug wiedermal. 💡

    Hallo volkard,
    ich fände es wünschenswert, wenn man hier auch mal nicht immer nur schreibt "Unfug" oder "Schwachsinn" sondern das Ganze auch mal kurz begründet. Mir reicht auch ein Link zu dem passenden Thema. Das sollte denke ich ja drin sein, oder nicht?
    Viele Grüße,
    Jakob

    SeppJ schrieb:

    jb schrieb:

    Wie verändert man den Zeichensatz? (Quellcode-Datei in ein anderes Format konvertieren?) Hast Du ein Beispiel, wann ich gezielt den Zeichensatz ändern möchte?

    Ich bezog mich auf den Zeichensatz, den das hier gezeigte Programm unterstützt. Vielleicht möchte der Autor später auch mal Ziffern und Sonderzeichen als Elemente des Spiels haben.

    Danke für die Erklärung.



  • jb schrieb:

    volkard schrieb:

    __jb__ schreibt Unfug wiedermal. 💡

    Hallo volkard,
    ich fände es wünschenswert, wenn man hier auch mal nicht immer nur schreibt "Unfug" oder "Schwachsinn" sondern das Ganze auch mal kurz begründet. Mir reicht auch ein Link zu dem passenden Thema. Das sollte denke ich ja drin sein, oder nicht?
    Viele Grüße,
    Jakob

    Schwachsinn.

    Ich bin in aller Ausführlichkeit und sogar mit Links auf ALLE Deine Argumente eingegangen, die Du angegeben hast, warum Dein Vorschlag eleganter sein sollte: nämlich gar keine.
    Und so prima ausgearbeitet war der Vorschlag eh nicht. Sonst hättest Du bemerkt, daß er zerbröselt. Die Doppeltheit der Liste ist doch das einzige Problem, und die würde schon von alleine wegfliegen, wenn Du den Code anfangen würdest aufzuhübschen. Wieso soll ich mir zehnmal mehr Arbeit machen als Du?

    Ich erwarte, daß weniger Unfug gepostet wird. Und falls doch, erlaube ich mir, gelegentlich aufzuzeigen.

    Auch erwarte ich von Fragestellern, daß sie den Code hier im Forum posten und nicht bei einem Drittanbieter, und daß die Mods den Code nachtragen.



  • volkard, da der "__jb__ schreibt Unfug wiedermal" Beitrag der erste von dir in diesem Thread ist. Gehe ich stark davon aus, dass Du einen anderen Beitrag von mir und Thread meinst. Außer du hast hier noch einen Post unter einem anderen Nick eingebracht!? Ja, ich sehe das auch so, dass du in den anderen Threads immer fachlich und professionell auf meine (Gegen-)Fragen geantwortet oder Argumentionen reagiert hast, finde ich auch total super 👍 👍 👍



  • lemon03 schrieb:

    Kann er dann nicht gleich seine char-Arrays so füllen?

    std::string index, pruef; //strings sind eigentlich char-Arrays
        char letter, letterpruef;
    
        for (int i=0; i<26; i++) //Anzahl Buchstaben vom Alphabet
        {
            index.push_back(char(65+i)); //füllen ab 'A'
            pruef.push_back(char(97+i)); //füllen ab 'a'
    
        }
    
      letter = index.at(a);
      letterpruef = pruef.at(a);
    

    (uh, 5-mal bearbeitet :D)

    Selten sinnvoll. So ein

    char alphabet[]="abcdefghijklmnopqrstuvwxyz0123456789.-,";
    

    steht auch bei mir normalerweise drin. Passwortgenerator, Bruteforcer, Dateinamengeneratur…
    Ich will später eh das Alphabet ändern können, so wie D4RKS0UL23 später das Spiel anpassen will, um zum Beispiel die Tasten auf der Grundlinie "asdfghjklöä#" schneller blind zu finden und immer mal wieder eine Taste dazunehmen mag.
    Ausnahme ist rot13, da benutze ich zum Initialisieren eine Schleife über alle Buchstaben.



  • lemon03 schrieb:

    Oder gibt es hier einen speziellen Grund für char[], den ich gerade nicht sehe?

    Der spezielle Grund ist, dass später ja überprüft wird ob der getippte Buchstabe korrekt ist.

    Zu beginn wird eine Zufallszahl von 0-25 generiert; die Zahl ist im int a gespeichert. Wenn die Zahl steht schaut das Programm im char-array an position a, und speichert den Buchstaben an der Position (a = 0 -> A, a = 1 -> B usw.)

    Wenn nun eine Taste getippt wurde, nimmt das Programm diese Taste und speichert sie in einer char-Variable. Danach schaut er im 2. Array (pruef), wieder an position a, ob der getippte buchstabe mit dem im Arraay übereinstimmt. Wenn ja dann gibt's Punkte, wenn nicht, dann nicht.

    Ich wüsste nicht wie sich soetwas einfach nur mit

    string pruef = "abcdefghijklmnopqrstuvwxyz";
    

    realisieren lässt.


Anmelden zum Antworten