Mastermind in C++
-
Hi,
ich muss zur Zeit das Spiel Mastermind in C++ programmieren und habe 2 "kleine" probleme ...
ich habe dort wo meine Probleme auftauchen einen kommentar in den code geschrieben.
wäre nett wenn sich das mal jemand angucken könnte ...
#include <iostream> #include <conio.h> #include <string> #include <cstdlib> #include <ctime> #include <ctype.h> using namespace std; string name; int spielerCode[4], computerCode[4], trefferFundP=0, trefferFarbe=0; bool positionHatTreffer[4]; void zufallsCode(); void eingabeCode(); void codesVergleichen(); void pruefeFundP(); void pruefeFarbe(); void menu(); void spiel(); void regeln(); void hilfe(); void regeln() { char neu; cout << "Spielregeln" << endl; cout << "Der Computer generiert einen Zahlencode aus 4 Zahlen," << endl; cout << "der nicht bekannt gegeben wird." << endl; cout << "Keine der 4 Zahlen darf den Wert 4 ueberschreiten" << endl; cout << endl; cout << "Diesen Zahlencode gilt es fuer den Spieler zu erraten. Er hat 8 Versuche." << endl; cout << endl; cout << "Wenn eine Zahl vorhanden ist wird eine '#' ausgegeben." << endl; cout << endl; cout << "Wenn eine Zahl vorhanden und an der richtigen Stelle ist, wird ein '$'" << endl; cout << "ausgegeben" << endl; cout << "In beiden Faellen wird nicht bekannt gegeben, an welcher Stelle diese Zahl steht" << endl; cout << endl; cout << "Es ist moeglich das eine Zahl mehrmals vorkommt." << endl; cout << endl; cout << "Wenn nach den 8 Versuchen der Code nicht erraten wurde wird er ausgegeben." << endl; cout << endl; cout << "Zurueck zum Menue <m>" <<endl; neu = getch(); system("cls"); if(neu='m') { menu(); } } ////////////////////////////////////////////////////////////////////////////////////////////////// void hilfe() { char neu; cout << "Hier Hilfe Funktion eingeben" << endl; cout << "Zurueck zum Menue <m>" <<endl; getch(); system("cls"); if(neu='m') { menu(); } } ////////////////////////////////////////////////////////////////////////////////////////////////// void zufallsCode() { int zaehler; char choice; srand (time(NULL)); for (zaehler=0;zaehler<4;zaehler++) { computerCode[zaehler]=rand()%4; } cout << computerCode[0] << computerCode[1] << computerCode[2] << computerCode[3] << endl; } ////////////////////////////////////////////////////////////////////////////////////////////////// void eingabeCode() { int zaehler; for (zaehler=0;zaehler<=3;zaehler++) { cin >> spielerCode[zaehler]; } } ////////////////////////////////////////////////////////////////////////////////////////////////// void pruefeFundP() { int i=0; while(i<4) { if(computerCode[i]==spielerCode[i]) { trefferFundP=trefferFundP+1; positionHatTreffer[i]=true; } i=i+1; } } ////////////////////////////////////////////////////////////////////////////////////////////////// void pruefeFarbe() //diese funktion funktioniert nicht. Hier sollte eigentlich überprüft werden ob die Zahlen Irgendwo in dem zufallscode drin vorkommen, //es soll nur nicht püberprüft werden an welcher position ... //hier komm ich gar nicht feiter ... ich schätze auch mal das in der Funktion irgendwo noch nen logischer fehler ist //wäre nett wenn mir da jemand helfen könnte ;P { int j=0, i; while(j<4) { if(computerCode[j] != spielerCode[j]) { if(positionHatTreffer[j]==false) { i=0; while(i<4) { if(computerCode[i]==spielerCode[j]) { if(positionHatTreffer[i]=false) { trefferFarbe=trefferFarbe+1; positionHatTreffer[i]=true; i=4; } } i=i+1; } j=j+1; } } } } ////////////////////////////////////////////////////////////////////////////////////////////////// void codesVergleichen() { char neu; int ende = 8; pruefeFundP(); // pruefeFarbe(); cout << "Anzahl der Treffer, bei denen Farbe und Position uebereinstimmen: " << trefferFundP << endl; cout << "Anzahl der Treffer, bei denen die Farbe stimmt, aber die Position falsch ist#" << trefferFarbe << endl; do //der sollte hier eigentlich nach dem 8ten versuch aufhören, macht der aber nicht. das is irgendwie ne endlos schleife //wäre nett wenn mir jemand sagen wodran es liegt bzw. wie ich den fehler behebe. { trefferFundP=0; trefferFarbe=0; cout << "Bitte Code erneut eingeben: " << endl; cout << ende << endl; ende--; cout << endl; eingabeCode(); codesVergleichen(); } while(ende>0); cout << "Zurueck zum Menue <m>" <<endl; neu = getch(); system("cls"); if(neu='m') { menu(); } } ////////////////////////////////////////////////////////////////////////////////////////////////// void spiel() { cout << "Mastermind" << endl; cout << endl; zufallsCode(); eingabeCode(); codesVergleichen(); } ////////////////////////////////////////////////////////////////////////////////////////////////// void menu() { char choice; system("cls"); cout << "Hallo " << name << endl; cout << endl; cout << "Bitte Auswaehlen" << endl; cout << "Regeln <r>" << endl; cout << "Hilfe <h>" << endl; cout << "Spielen <s>" << endl; cout << "Spiel beenden <b>" << endl; cout << endl; cout << "Ihre Wahl: " << endl; choice = getch(); //cin >> choice; system("cls"); switch(choice) { case 'b': cout << endl; cout << "Beenden" << endl; break; case 'r': cout << endl; regeln(); break; case 'h': cout << endl; hilfe(); break; case 's': cout << endl; spiel(); break; default: cout << endl; cout << "Ungueltige Eingabe" << endl; break; } } ////////////////////////////////////////////////////////////////////////////////////////////////// void main() { cout << "Bitte Namen eingeben" << endl; cin >> name; menu(); }thx schonmal im voraus ..

-
Es würde die Fehlersuche erleichtern, wenn du ein Beispiel angeben würdest, bei dem es nicht so, wie es soll, funktioniert (Eingabe+falsche Ausgabe) und anschließend kurz angeben, was er denn ausgeben sollte.
-
also,
1. nachdem die funktion Spiel aufgerufen wird, gibt er einen 4 Stelligen Code aus, den soll man dann im fertigen Spiel erraten.
danach hat man die möglichkeit 4 Zahlen einzugeben.
Jetzt gibt er eigentlich die "Anzahl der Treffer, bei denen Farbe und Position uebereinstimmen: " aus, das funkioniert auch noch, aber danach soll er die "Anzahl der Treffer, bei denen die Farbe stimmt, aber die Position falsch ist:" ausgeben, was er aber nicht macht, sobald die funktion pruefeFarbe(); aufgerufen wird is das programm zuende ...2.hier sollte er die schleife eigentlich nach dem 8ten durchlauf beenden ws er aber nicht macht ...
-
vgl. = (Zuweisung) und == (Vergleich)
Der erste Fehler wo ich sehe
//EDIT1
In der Funktion codesVergleichen() rufst du codesVergleichen() auf.
Das nennt man rekursion und ist hier wohl nciht erwünscht
//EDIT2
Hab das Spiel mal compiliert und ich blicks net, das spiel ist in sich unlogisch.
Überdenk lieber nochmal genau wie du was am besten umsetzten tust.
Außerdem enthält es unbenutzte variabeln. Und für den user wär es logischer nur eine 4-stellige-zahl einzugeben und nicht 4 mal eine 1-stellige.Außerdem solltest du überlegen ob du wirklich so funktionen und schleifen bauchst.
Weniger ist manchmal mehr. z.B. das menu würd ich direkt in die main machen
und codesVergleichen direkt in die spiel funktion.Es sind aber auch ein paar gute Ansätze dabei, also nicht verzweifeln

-
Dein Problem liegt daran, dass du in der Funktion CodesVergleichen, die du in deiner Schleife aufrufst immer wieder den Befehl
int ende = 8;Selbst wenn du die Schleife in eine andere Funktion packst darfst du die Deklaration der Variable, von der die Schleife abhängt, nicht in der Funktion machen, die durch deine Schleife aufgerufen wird, also du setzt im Moment ende auf 8, ziehst 1 ab, setzt wieder ende auf 8, und so weiter...
Mit deinem anderen Problem kann ich dir im Moment noch nicht helfen.
-
Hallo,
hab ein bischen mit dem Code rumgespielt...
Ist zwar nicht schön aber er läuft und ich hatte im Augenblick nicht mehr Zeit...Die Änderungen wurden größtenteils Kommentiert.
#include <iostream> #include <list> #include <algorithm> #include <conio.h> #include <string> #include <cstdlib> #include <ctime> #include <ctype.h> // variablen wurden lokalisiert std::string name; // nicht benötigte foreward declarations wurden entfernt void menu(void); // Funktion regeln gibt die Spielregeln auf dem Bildschirm aus void regeln(void) { using namespace std; char neu; // habe im ganzen Abschnitt die "<< endl" entfernt und als // end-line-character '\n mit in die strings genommen cout << "Spielregeln:\n"; cout << "Der Computer generiert einen Zahlencode aus 4 Zahlen,\n"; cout << "der nicht bekannt gegeben wird.\n"; cout << "Keine der 4 Zahlen darf den Wert 4 ueberschreiten\n\n"; cout << "Diesen Zahlencode gilt es fuer den Spieler zu erraten. Er hat 8 Versuche.\n\n"; cout << "Wenn eine Zahl vorhanden ist wird eine '#' ausgegeben.\n\n"; cout << "Wenn eine Zahl vorhanden und an der richtigen Stelle ist, wird ein '$'\n"; cout << "ausgegeben\n"; cout << "In beiden Faellen wird nicht bekannt gegeben, an welcher Stelle diese Zahl steht\n\n"; cout << "Es ist moeglich das eine Zahl mehrmals vorkommt.\n\n"; cout << "Wenn nach den 8 Versuchen der Code nicht erraten wurde wird er ausgegeben.\n\n"; cout << "Zurueck zum Menue <m>\n"; // hier habe ich die if-Anweisung ersetzt da das Programm sonst bei einer falschen Eingabe abstürzt // und der Bildschirm erst gelöscht werden soll, wenn der Benutzer die Regeln verstanden hat. do cin >> neu; while (neu != 'm'); system("cls"); menu(); } // Funktion hilfe (Bemerkung: nur stub-routine) void hilfe(void) { std::cout << "Hier Hilfe Funktion eingeben\n"; std::cout << "Zurueck zum Menue <m>\n"; // hier habe ich die if-Anweisung ersetzt da das Programm sonst bei einer falschen Eingabe abstürzt // und der Bildschirm erst gelöscht werden soll, wenn der Benutzer die Regeln verstanden hat. char neu; do std::cin >> neu; while (neu != 'm'); system("cls"); menu(); } // Funktion zufallsCode erzeugt einen vier-stelligen Zufallscode // dessen vier stellen jeweils die Werte 1,2,3 oder 4 haben können void zufallsCode(int *computerCode) { srand (unsigned int(time(0))); // variable zaehler wurde lokalisiert for (int zaehler = 0; zaehler < 4; zaehler++) computerCode[zaehler] = rand()%4 + 1; } // Funktion eingabeCode übernimmt den vierstelligen Code des // Spielers und prueft den Bereich der Eingabe void eingabeCode(int *spielerCode) { // variable zaehler wurde lokalisiert for (int i = 0; i < 4; i++) { bool loop; do { loop = false; std::cout << "Code[" << i + 1 << "] = "; std::cin >> spielerCode[i]; if (spielerCode[i] > 4 || spielerCode[i] < 1) { loop = true; std::cout << "\nEingabe liegt nich im Bereich [1, 4]!\n\a"; std::cout << "Bitte versuchen Sie es erneut...\n\n"; } } while (loop); } } // pruef-Funktionen wurden in der Funktion pruefe vereinigt void pruefe(int &hit, int &farbe, const int *CompCode, const int *UserCode) { // zunächst sollen die Hits aus dem Feld genommen werden // um eine Doppelzählung in den farben zu vermeiden int entries = 0; int table[4]; for (int i = 0; i < 4; i++) if (CompCode[i] == UserCode[i]) hit++; else table[entries++] = i; // im verbleibenden Feld werden die Übereinszimmungen in eine List eingetragen std::list<int> hitList; for (int i = 0; i < entries; i++) for (int j = 0; j < entries; j++) if (CompCode[table[i]] == UserCode[table[j]]) hitList.push_back(UserCode[table[i]]); // as der List werden die vorkommenden Farben ausgewählt. // doppelt vorkommende farben werden somit nur einmal gezählt for (int i = 1; i <= 4; i++) { std::list<int>::iterator iter = std::find(hitList.begin(), hitList.end(), i); if (iter != hitList.end()) farbe++; } } // funktion spiel ruft die Funktion zufallsCode auf und gibt dem Benutzer // acht versuche das Spiel zu gewinnen void spiel(void) { std::cout << "Mastermind\n\n"; int CompCode[4]; zufallsCode(CompCode); int trys = 8; bool loose = true; do { int hit = 0; int farbe = 0; int UserCode[4]; eingabeCode(UserCode); pruefe(hit, farbe, CompCode, UserCode); std::cout << "\nhits ($): " << hit; std::cout << "\nFarbe (#): " << farbe << "\n\n"; if (hit == 4) loose = false; } while (--trys > 0 && loose); if (loose) { std::cout << "Sie haben leider verloren!\n\n"; std::cout << "Der Code war\n"; for (int i = 0; i < 4; i++) std::cout << CompCode[i]; std::cout << "\n\n"; } else std::cout << "Sie haben Gewonnen!\n\n"; char neu; std::cout << "Zurueck zum Menue <m>\n"; // hier habe ich die if-Anweisung ersetzt da das Programm sonst bei einer falschen Eingabe abstürzt // und der Bildschirm erst gelöscht werden soll, wenn der Benutzer die Regeln verstanden hat. do std::cin >> neu; while (neu != 'm'); system("cls"); menu(); } void menu(void) { using namespace std; char choice; system("cls"); cout << "Hallo " << name << "\n\n"; cout << "Bitte Auswaehlen\n"; cout << "Regeln <r>\n"; cout << "Hilfe <h>\n"; cout << "Spielen <s>\n"; cout << "Spiel beenden <b>\n\n"; cout << "Ihre Wahl:\n"; choice = getch(); //cin >> choice; system("cls"); cout << endl; switch(choice) { case 'b': cout << "Beenden\n"; break; case 'r': regeln(); break; case 'h': hilfe(); break; case 's': spiel(); break; default: //cout << "Ungueltige Eingabe" << endl; // ruf doch hier menu() auf anderfalls bricht das Programm ab oder menu(); break; } } void main(void) { std::cout << "Bitte Namen eingeben\n"; std::cin >> name; menu(); }Viele Grüße
-
hier noch eine Variante, da die anderen Prüf-Sourcen nicht so arbeiten
wie ich mir das vorstelle :void pruefe() { int i, j; int tmpCode[4]; for(i=0; i<4; i++) tmpCode[i] = computerCode[i]; // kopieren da _Code[i] = -1 sonst Orginal zerstören wuerde for(i=0; i<4; i++) { if(tmpCode[i]==spielerCode[i]) // Volltreffer { trefferFundP=trefferFundP+1; tmpCode[i] = -1; // markieren als versenkt } } for(i=0; i<4; i++) for(j=0; j<4; j++) { if(tmpCode[i]==spielerCode[j]) // Streifschuss { trefferFarbe=trefferFarbe+1; tmpCode[i] = -1; // markieren als angesengt } } }
-
ach ja, da sind auch noch einige wesentliche Aenderungen:
void spiel() { char neu; int ende = 8; zufallsCode(); do { trefferFundP=0; trefferFarbe=0; eingabeCode(); pruefe(); cout << "Anzahl der Treffer, bei denen Farbe und Position uebereinstimmen: " << trefferFundP << endl; cout << "Anzahl der Treffer, bei denen die Farbe stimmt, aber die Position falsch ist:" << trefferFarbe << endl; if(trefferFundP==4) ende=0; cout << "Bitte Code erneut eingeben: " << endl; cout << "noch " << ende << " Versuche" << endl; ende--; cout << endl; } while(ende>0); cout << computerCode[0] << computerCode[1] << computerCode[2] << computerCode[3] << endl; cout << "Zurueck zum Menue <m>" <<endl; neu = getch(); system("cls"); if(neu=='m') { menu(); } }ist ja hoffentlich klar, tuning ist immer möglich, z.b. system("xy") durch
geeigneteres ersetzen.ich bevorzuge bei Spielen die direkte Eingabe von Buchstaben ohne "Enter".
weiter würde ich statt der "Farben" 0 bis 3 --> 1 bis 4 bevorzugen; das tippt
sich schneller.viel Spass mit den Schnipseln.