Bringe Minigame Ki nicht zusammen



  • Hallo Leute!
    önntet ihr mir Bitte bei der Ki meines Computer gegners helfen?
    Er soll eine gewisse Anzahl an Münzen intelligent auswählen.
    Hier ist der Code:

    #include <iostream>
    #include <windows.h>
    #define COINS 80
    using namespace std;
    
    int TakeAI(int Count)
    {
      if(Count>2&&Count<5)return 3;
      if(Count>4&&Count<7)return 5;
      if(Count>6&&Count<10)return 7;
      if(TakeAI(Count-3)==3)return 3;
      if(TakeAI(Count-5)==5)return 5;
      if(TakeAI(Count-7)==7)return 7;
      else return 3;
    }
    
    void SetColor(int color)
    {
      HANDLE hcon = GetStdHandle(STD_OUTPUT_HANDLE);
      SetConsoleTextAttribute(hcon, color);
    } 
    
    void Rules()
    {
      SetColor(4);
      cout << "Willkommen in meinem Spiel!" << endl;
      cout << "Sie spielen gegen den Computer." << endl;    
      cout << "Am Anfang ist eine gewisse Anzahl an Muenzen im Topf." << endl;
      cout << "Jeden Zug nimmt der jeweilige Spieler entweder 3, 5 oder 7 Muenzen." << endl;
      cout << "Der Spieler der keine Muenzen mehr nehmen kann hat verloren!" << endl;
      cout << "Viel Spass noch!\n" << endl;
      SetColor(7);
    }
    
    bool Starter()
    {
      char starter;
      SetColor(2);
      cout << "Wollen Sie das Spiel beginnen?(y/n) "; 
      cin >> starter;
      SetColor(7);
      if(starter=='y'||starter=='Y')
      {
        return 1;
      }
      else
      {
        return 0;
      } 
    }
    
    int Take()
    {
      int choice;
      cin >> choice;
      while(!(choice==3||choice==5||choice==7))
      {
        cout << "Die Zahl muss entweder 3, 5 oder 7 sein!" << endl;
        cout << "Wieviele Muenzen wollen Sie vom Topf nehmen? ";
        cin >> choice;
      }
      return choice;                             
    }
    
    int GetCount()
    {
      SetColor(3);
      cout << "Die Anzahl der Muenzen ist: " << COINS << "\n";
      SetColor(7);
    }
    
    void Play()
    {
      GetCount();
      int Count = COINS;
      bool Turn = Starter();
      int taken = 0;
      while(Count>2)
      {
        if(Turn==1)
        {
          SetColor(6);
          cout << "\nEs befinden sich noch " << Count << " Muenzen im Topf.\n" << endl;
          SetColor(10);
          cout << "Sie sind am Zug." << endl;
          cout << "Wie viele Muenzen wollen Sie vom Topf nehmen? ";
          taken = Take();
          Count -= taken;
          Turn=0;
          if(Count<=2)
          {
            SetColor(6);
            cout << "\nEs befinden sich noch " << Count << " Muenzen im Topf.\n" << endl;
            SetColor(4);
            cout << "\nSie haben das Spiel gewonnen!\n" << endl;
            SetColor(7);
            system("PAUSE");
          } 
        }
        if(Turn==0)
        {
          SetColor(6);
          cout << "\nEs befinden sich noch " << Count << " Muenzen im Topf.\n" << endl;
          SetColor(11);
          cout << "Der Computer ist am Zug." << endl;
          cout << "Wie viele Muenzen wollen Sie vom Topf nehmen? ";
          taken = TakeAI(Count);
          cout << taken << endl;
          Count -= taken;
          Turn=1;  
          if(Count<=2)
          {
            SetColor(6);
            cout << "\nEs befinden sich noch " << Count << " Muenzen im Topf.\n" << endl;
            SetColor(4);
            cout << "\nSie haben das Spiel verloren!\n" << endl;
            SetColor(7);
            system("PAUSE");
          }       
        }        
      }
    }
    
    int main()
    {
      Rules();
      Play();
    }
    


  • Was willst du jetzt genau?
    Davon abgesehen dass GetCount() nichts zurückliefert schauts eh nicht schlecht aus...



  • Um im letzten Zug gewinnen zu können muss man 3 bis 9 Münzen haben:

    3: ich nehme 3 -> bleiben 0 -> gewonnen
    4: ich nehme 3 -> bleiben 1 -> gewonnen
    5: ich nehme 5 -> bleiben 0 -> gewonnen
    6: ich nehme 5 -> bleiben 1 -> gewonnen
    7: ich nehme 7 -> bleiben 0 -> gewonnen
    8: ich nehme 7 -> bleiben 1 -> gewonnen
    9: ich nehme 7 -> bleiben 2 -> gewonnen

    Um im letzten Zug verlieren zu müssen (wenn der Gegner optimal spielt) muss man 10 bis 12 Münzen haben:
    10: ich kann 3-7 Münzen nehmen, führt zu 3-7 für den Gegner -> Gegner kann gewinnen (siehe oben)
    11: ich kann 3-7 Münzen nehmen, führt zu 4-8 für den Gegner -> Gegner kann gewinnen
    12: ich kann 3-7 Münzen nehmen, führt zu 5-9 für den Gegner -> Gegner kann gewinnen

    Ab 13 kann ich wieder fix gewinnen, indem ich 3 nehme, bleiben den Gegner 10 -> er muss verlieren (siehe oben).
    14 -> ich nehme 3 -> 11 -> Gegner muss verlieren
    15 -> ich nehme 5 -> 10 -> Gegner muss verlieren
    16 -> ich nehme 5 -> 11 -> Gegner muss verlieren
    17 -> ich nehme 7 -> 10 -> Gegner muss verlieren
    18 -> ich nehme 7 -> 11 -> Gegner muss verlieren
    19 -> ich nehme 7 -> 12 -> Gegner muss verlieren

    Und hier sollte einem jetzt ein Muster auffallen.

    Der Trick dabei ist einfach zu sehen dass man dem Gegner eine Anzahl an Münzen hinlegt die mit 0 1 oder 2 aufhört (die Stellen davor sind egal).
    Angenommen ich spiele so dass nach meinem Zug 101 Münzen übrig bleiben, dann habe ich schon gewonnen: nimmt der Gegner 3 nehme ich 7, nimmt der Gegner 5 nehme ich auch 5, nimmt der Gegner 7 nehme ich 3. Die Summe beider Züge ist immer 10, und nach meinem nächsten Zug hat der Genger es mit 91 Münzen zu tun. Dann 81, 71, ..... 11, 1 -> Gegner hat verloren.

    Daraus lässt sich schnell eine Funktion formulieren:

    int TakeAI(int Count)
    {
        assert(Count >= 3);
        switch(Count % 10)
        {
        case 0:
        case 1:
        case 2:
            // Hier ist es im Prinzip egal was wir tun, da wir (wenn der Gegner optimal spielt) schon verloren haben.
            return 3;
    
        case 3:
        case 4:
            return 3;
        case 5:
        case 6:
            return 5;
        case 7:
        case 8:
        case 9:
            return 7;
        }
    }
    

    Um das ganze etwas weniger transparent und offensichtlich zu machen könnte man bei "case 5" hin und wieder auch nur 3 Münzen nehmen, und bei "case 7" hin und wieder nur 5. Genauso könnte man bei 0-2 zufällig entscheiden.
    Gegen menschliche Spieler wäre das sicher sinnvoll, da dadurch wie gesagt die Strategie nicht so schnell offensichtlich wird.



  • Vielen Dank für die schnelle Antwort!
    Aber eine Frage noch: was bringt die Funktion assert?



  • Hallo

    assert

    bis bald
    akari


Anmelden zum Antworten