Schere Stein Papier



  • Hab mal ein kleines Schere Stein Papier für die win32 console geschrieben.
    😃
    Was haltet ihr davon?
    viel Spass beim spielen 😉

    #include <iostream>
    #include <ctime>
    #include <string>
    
    using namespace std;
    
    class Symbol{
          public:
                 Symbol(){
                          gewinnt      = 0;
                          verliert     = 0;
                          bezeichnung  = "";
                          }
                 string   bezeichnung;
                 Symbol*  gewinnt;
                 Symbol*  verliert;
          };
    
    int main(){
        const int MAX_SYMBOL = 3;
    
        int iComputer;
        int iSpieler;
    
        string sEingabe;
    
        Symbol Schere;
        Symbol Stein;
        Symbol Papier;
        Symbol *Symbole[MAX_SYMBOL] = {
               &Schere,
               &Stein,
               &Papier
               };
    
        srand((unsigned int) time(0));
    
        Schere.bezeichnung = "Schere";
        Stein.bezeichnung  = "Stein";
        Papier.bezeichnung = "Papier";
    
        Schere.verliert = &Stein;
        Schere.gewinnt  = &Papier;
    
        Stein.verliert  = &Papier;
        Stein.gewinnt   = &Schere;
    
        Papier.verliert = &Schere;
        Papier.gewinnt  = &Stein;
    
        for(;;){
                        cin >> sEingabe;
                        if(sEingabe[0] == 'e' || sEingabe[0] == 'E') break;
                        iSpieler = -1;
                        for(int i = 0; i < MAX_SYMBOL; i++){
                                if(sEingabe == Symbole[i]->bezeichnung)
                                            iSpieler = i;
                                }
                        if(iSpieler == -1) continue;
                        iComputer = rand()%MAX_SYMBOL;
                        cout << Symbole[iSpieler]->bezeichnung << " vs. " << Symbole[iComputer]->bezeichnung << endl;
                        if(iComputer == iSpieler) cout << "Unentschieden!" << endl;
                        else if(Symbole[iComputer]->gewinnt == Symbole[iSpieler]) cout << "Verloren!" << endl;
                        else cout << "Gewonnen!" << endl;
                        }
    
    }
    

    mfG danie



  • Bei Zeile 37 hast du einen C-Cast. Und ich würde statt einer Endlosschleife mit einem break eher eine normale Schleife und eine kluge Abbruchbedingung nutzen.

    Tipp: Vermeide using namespace std; , es ruft Bezeichnerkonflikte hervor.
    Tipp: Du hast einige int s, die du unsigned hättest machen können.
    Tipp: Wenn alles einer Klasse public ist, kannst du gleich ein struct machen.

    Übung: Versuche es mal mit Enumatoren und einer std::map .

    Gut gemach! Weiter so 👍



  • SUPER! Kompiliert mit VS2010 fehlerfrei. Leider fehlt eine Anleitung und
    das Programm ist ohne Quelltext und OOP-Kenntnisse fast nicht spielbar.

    Eine Hilfe zum Programmstart wäre gut:

    cout << "Geben sie bitte ";
      for(int i = 0; i < MAX_SYMBOL; i++)
         cout << Symbole[i]->bezeichnung << " ";
      cout << "oder E (=Ende) ein" <<endl;
    

    Sowie ein Userfeedback in Fehlerfall:

    if(iSpieler == -1) {
    cout << "Keine gueltige eingabe" << endl;
    continue;
    }

    Danke für das nette Beispiel 🙂



  • Habe das Proggi nochmal etwas optimiert:

    #include <iostream>
    #include <ctime>
    #include <string>
    
    using namespace std;
    
    enum ERGEBNIS  {unendschieden, gewonnen, verloren};
    enum ELEMENT   {Schere, Stein, Papier, MAXELEMENTS};
    
    int Name2Num(string name) {
    		 if(name == "Schere") return Schere;
    		 if(name == "Stein")  return Stein;
    		 if(name == "Papier") return Papier;
    		 return -1;
       }
    
    class Symbol{
    
    public:
       Symbol(string name){
                  bezeichnung  = name;
    			  gewinnt = -1; verliert = -1; 
    			  // Spielregeln
    			  if(name == "Schere") { gewinnt = Papier; verliert = Stein; }
                     // besser waere: gewinnt = Name2Num("Stein"); verliert ist überflüssig
    
    			  if(name == "Stein")  { gewinnt = Schere; verliert = Papier; }
    			  if(name == "Papier") { gewinnt = Stein; verliert = Schere; }
       }
       int Vergleich(string name);
       string GetName(){ return bezeichnung; };
    
    private:
       string   bezeichnung;
       int  gewinnt;
       int  verliert;
       };
    
    int Symbol::Vergleich(string name) {
      int ergebnis = unendschieden;  // bezeichnung == name 
      int gegner  = Name2Num(name);
    
      if(gegner == -1) ergebnis = -1; 
      if(gegner == gewinnt)  ergebnis = verloren; 
      if(gegner == verliert) ergebnis = gewonnen;
    
      return ergebnis;
    }
    
    int main(){
    
    	int iComputer, iSpieler, iErgebnis;
    
        string sEingabe;
    
        Symbol CSchere("Schere");
        Symbol CStein("Stein");
        Symbol CPapier("Papier");
    
        Symbol *Symbole[MAXELEMENTS] = {
               &CSchere, &CStein, &CPapier
               };
    
        srand((unsigned int) time(0));
    
     	cout << "Geben sie bitte ";
    	for(int i = 0; i < MAXELEMENTS; i++)
            cout << Symbole[i]->GetName() << " ";
    	cout << "oder E (=Ende) ein" << endl;
    
        for(;;){
    
    		cout << ">";
    		cin >> sEingabe;
            if(sEingabe[0] == 'e' || sEingabe[0] == 'E') break;
    
    		iSpieler = Name2Num(sEingabe);
    
    		if(iSpieler == -1) {
    			cout << "Keine gueltige eingabe" << endl;
    			continue;
    		}
    
    		iComputer = rand()%MAXELEMENTS;
    
    		cout << Symbole[iSpieler]->GetName() << " vs. " << Symbole[iComputer]->GetName() << endl;
    
    		iErgebnis = Symbole[iComputer]->Vergleich(sEingabe);
    
            switch(iErgebnis) {
    		case unendschieden:
    			cout << "Unentschieden!" << endl; break;
    		case gewonnen:
    			cout << "Gewonnen!" << endl; break;
    		case verloren:
    			cout << "Verloren!" << endl; break;
    		default:
    			cout << "Kein Ergebnis ?" << endl;
    		}
    	}
    
    }
    

    1. Membervariablen nicht public
    2. Elementname im Konstruktor angebbar
    3. Spielregeln in der Klasse gekapselt
    4. Enums verwendet

    - Vielleicht wäre es besser als Parameter für die Memberfkt. int zu
    verwenden.

    - Die Membervariable verliert ist überflüssig.

    Das Problem mit std kann ich nicht nachvollziehen. Ich habe jedenfalls keine Lust bei jedem cout auch noch den Namespace anzugeben ...



  • merano schrieb:

    Das Problem mit std kann ich nicht nachvollziehen.

    Bezeichnerkollision?
    Zeile 62 ein unnötiger C-Cast.
    Zudem läuft dein Code mit C++0x nicht mehr ( enum missbraucht!).
    Zudem noch unlokale Deklarationen bei Zeile 50 & Zeile 52.
    Wieder Spaghetti-Code ( continue und Schleifen- break )...
    Keine Stream-Checks ( EOF , fail und bad ).
    Dann noch ein rohes Array 🙄 .
    Und eine #include -Direktive fehlt: std::rand und std::srand aus <cstdlib> .
    Zudem hätte man Zeilen 41 bis 43 eleganter lösen können.
    Und was sollen all die Präfixe?



  • EOutOfResources schrieb:

    Zudem läuft dein Code mit C++0x nicht mehr ( enum missbraucht!)

    Könnten wir denn mal eine politisch korrekte Version von dir bekommen ?

    Übrigens der C++0x ist kein Standard und wird wohl erst im Herbst 2011 als
    Standard C++11 fertig werden. Wir reden also ein Stück weit über ungelegte
    Eier 😃

    http://www.linux-magazin.de/NEWS/C-0x-wird-als-C-11-standardisiert

    Solange VS2010 nicht mal eine Warnung erzeugt sehe ich kein Problem - bin aber an Verbesserungen immer interessiert.

    EOutOfResources schrieb:

    Zudem hätte man Zeilen 41 bis 43 eleganter lösen können.

    Ja. Habe ich bereits zugestanden.

    EOutOfResources schrieb:

    Und was sollen all die Präfixe?

    Die sogenannte Ungarische Notation ist unter Windows absolut üblich - macht den
    Code besser lesbar. Wen es stört, der kann seine Variablen auch anders benennen.



  • merano schrieb:

    EOutOfResources schrieb:

    Und was sollen all die Präfixe?

    Die sogenannte Ungarische Notation ist unter Windows absolut üblich - macht den
    Code besser lesbar. Wen es stört, der kann seine Variablen auch anders benennen.

    Die ungarische Notation (in der Form, wie du sie verwendest) ist Unsinn - das haben selbst die Microsoft'ler inzwischen eingesehen.



  • CStoll schrieb:

    Die ungarische Notation ist Unsinn

    Und für C++ überhaupt nicht geeignet.



  • ich hab die ungarische Notation auch früher öfter verwendet, aber bin inzwischen davon weg, weil es einfach nicht mehr nötig ist, bei all der Intellisense und den recht guten IDEs, die es inzwischen viel einfacher machen, den Hintergrund einer Variable zu erkennen.



  • Danke für die vielen Beiträge 👍

    ich versuche es gerade mit einer std::map umzusetzen, stehe aber auf dem Schlauch. Naja wenn ichs hinbekommen hab werde ich es posten. 😉


Anmelden zum Antworten