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.


Anmelden zum Antworten