Bug in der Tic Tac Toe implementierung



  • char feld[2]; // sind 2 chars
    // Zugriff
    feld[0] = 'x';
    feld[1] = 'o';
    

    beim anlegen von Arrays gibst Du die Größe des Arrays an.
    Beim Zugriff beginnt der Index bei 0 und endet bei n-1, wobei n die Größe des Arrays ist.


  • Mod

    ReALITY5 schrieb:

    Airdamn schrieb:

    char Spielfeld[2][2];
    

    das sind 2x2 Felder, Du brauchst aber 3x3

    Das nullte array element wird doch mit gezählt, oder?

    es gibt kein 'nulltes' element, wohl aber eines mit dem index 0 (das wäre das erste element). umgekehrt wird der index aber nur bis 1 - die dimensionsangaben bei der deklaration bestimmen die anzahl der elemente, nicht den höchsten index.



  • Wenn ich jetzt eine abfrage machen will, ob das feld belegt ist, verfängt sich das in einer endlosschleife, die funktion folgt:

    void tic_tac_toe::Spieler2_zug()
    {
    	int reihe=0;
    	int spalte=0;
    	while(Spielfeld[reihe-1][spalte-1]=='x')
    	{
    	cout<<"Reihe: ";
    	cin>>reihe;
    	cout<<"Spalte: ";
    	cin>>spalte;
    	}
    	Spielfeld[reihe-1][spalte-1]=='y';
    }
    


  • ich denke eher an

    void tic_tac_toe::Spieler2_zug()
    {
    	int reihe=0;
    	int spalte=0;
    	do	{
    	cout<<"Reihe: ";
    	cin>>reihe;
    	cout<<"Spalte: ";
    	cin>>spalte;
    	}while(reihe>=1 && reihe<=3 && spalte>=1 && spalte <=3 && Spielfeld[reihe-1][spalte-1]!='y')
    	Spielfeld[reihe-1][spalte-1]=='y';
    }
    


  • @ReALITY:

    Spielfeld[reihe-1][spalte-1]=='y';
    

    ist ein Vergleich, keine Zuweisung...vielleicht solltest Du Deinen Code mal genauer angucken :p



  • Der will jetzt immer noch net, jetzt is die ganze Zeit Spieler 1 am Zug

    void tic_tac_toe::Spieler1_zug()
    {
        int reihe=0;
        int spalte=0;
        while(Spielfeld[reihe-1][spalte-1]=='o')
        {
        cout<<"Reihe: ";
        cin>>reihe;
        cout<<"Spalte: ";
        cin>>spalte;
        }
        Spielfeld[reihe-1][spalte-1]='x';
    }
    


  • Ich habe das Problem gelöst mit der mehrfachbelegung und dem abfragen ob das feld schon belegt ist bzw ob das feld überhapt in der aaray grenze ist. Für alle die auch ein tic tac toe implementieren wollen hier meine implementierung

    #include<iostream>
    #include<iomanip>
    using namespace std;
    
    class tic_tac_toe
    {
    private:
    	char Spielfeld[3][3];
    public:
    	void Spieler1_zug();
    	void Spieler2_zug();
    	void anzeigen();
    	void gewonnen_s1();
    	void gewonnen_s2();
    	int check2(int reihe,int spalte);
    	int check1(int reihe,int spalte);
    	tic_tac_toe();
    };
    
    tic_tac_toe::tic_tac_toe()
    {
    	Spielfeld[0][0]='.';
    	Spielfeld[0][1]='.';
    	Spielfeld[0][2]='.';
    	Spielfeld[1][0]='.';
    	Spielfeld[1][1]='.';
    	Spielfeld[1][2]='.';
    	Spielfeld[2][0]='.';
    	Spielfeld[2][1]='.';
    	Spielfeld[2][2]='.';
    }
    
    void tic_tac_toe::Spieler1_zug()
    {
        int reihe=0;
        int spalte=0;
        while(reihe<1 || reihe>3 || spalte<1 || spalte>3 || Spielfeld[reihe-1][spalte-1]=='o' || Spielfeld[reihe-1][spalte-1]=='x')
        {
        cout<<"Reihe: ";
        cin>>reihe;
        cout<<"Spalte: ";
        cin>>spalte;
        }
        Spielfeld[reihe-1][spalte-1]='x';
    }
    
    void tic_tac_toe::Spieler2_zug()
    {
        int reihe=0;
        int spalte=0;
        while(reihe<1 || reihe>3 || spalte<1 || spalte>3 || Spielfeld[reihe-1][spalte-1]=='o' || Spielfeld[reihe-1][spalte-1]=='x')
        {
        cout<<"Reihe: ";
        cin>>reihe;
        cout<<"Spalte: ";
        cin>>spalte;
        }
        Spielfeld[reihe-1][spalte-1]='o';
    }
    
    void tic_tac_toe::anzeigen()
    {
    	int i;
    	int y;
    	for(i=0;i<3;i++)
    	{
    		for(y=0;y<3;y++)
    		{
    			cout<<setw(2)<<Spielfeld[y][i];
    		}
    		cout<<"\n\n";
    	}
    }
    
    void tic_tac_toe::gewonnen_s2()
    {
    	if(Spielfeld[0][0]=='o' && Spielfeld[0][1]=='o' && Spielfeld[0][2]=='o')
    	{
    		cout<<"Spieler 2 hat gewonnen!"<<endl;
    		void anzeigen();
    		exit(0);
    	}
    	if(Spielfeld[1][0]=='o' && Spielfeld[1][1]=='o' && Spielfeld[1][2]=='o')
    	{
    		cout<<"Spieler 2 hat gewonnen!"<<endl;
    		void anzeigen();
    		exit(0);
    	}
    	if(Spielfeld[2][0]=='o' && Spielfeld[2][1]=='o' && Spielfeld[2][2]=='o')
    	{
    		cout<<"Spieler 2 hat gewonnen!"<<endl;
    		void anzeigen();
    		exit(0);
    	}
    	if(Spielfeld[0][1]=='o' && Spielfeld[1][1]=='o' && Spielfeld[2][1]=='o')
    	{
    		cout<<"Spieler 2 hat gewonnen!"<<endl;
    		void anzeigen();
    		exit(0);
    	}
    	if(Spielfeld[0][0]=='o' && Spielfeld[1][0]=='o' && Spielfeld[2][0]=='o')
    	{
    		cout<<"Spieler 2 hat gewonnen!"<<endl;
    		void anzeigen();
    		exit(0);
    	}
    	if(Spielfeld[0][2]=='o' && Spielfeld[1][2]=='o' && Spielfeld[2][2]=='o')
    	{
    		cout<<"Spieler 2 hat gewonnen!"<<endl;
    		void anzeigen();
    		exit(0);
    	}
    	if(Spielfeld[0][0]=='o' && Spielfeld[1][1]=='o' && Spielfeld[2][2]=='o')
    	{
    		cout<<"Spieler 2 hat gewonnen!"<<endl;
    		void anzeigen();
    		exit(0);
    	}
    	if(Spielfeld[0][2]=='o' && Spielfeld[1][1]=='o' && Spielfeld[2][0]=='o')
    	{
    		cout<<"Spieler 2 hat gewonnen!"<<endl;
    		void anzeigen();
    		exit(0);
    	}
    }
    
    void tic_tac_toe::gewonnen_s1()
    {
    	if(Spielfeld[0][0]=='x' && Spielfeld[0][1]=='x' && Spielfeld[0][2]=='x')
    	{
    		cout<<"Spieler 1 hat gewonnen!"<<endl;
    		void anzeigen();
    		exit(0);
    	}
    	if(Spielfeld[1][0]=='x' && Spielfeld[1][1]=='x' && Spielfeld[1][2]=='x')
    	{
    		cout<<"Spieler 1 hat gewonnen!"<<endl;
    		void anzeigen();
    		exit(0);
    	}
    	if(Spielfeld[2][0]=='x' && Spielfeld[2][1]=='x' && Spielfeld[2][2]=='x')
    	{
    		cout<<"Spieler 1 hat gewonnen!"<<endl;
    		void anzeigen();
    		exit(0);
    	}
    	if(Spielfeld[0][1]=='x' && Spielfeld[1][1]=='x' && Spielfeld[2][1]=='x')
    	{
    		cout<<"Spieler 1 hat gewonnen!"<<endl;
    		void anzeigen();
    		exit(0);
    	}
    	if(Spielfeld[0][0]=='x' && Spielfeld[1][0]=='x' && Spielfeld[2][0]=='x')
    	{
    		cout<<"Spieler 1 hat gewonnen!"<<endl;
    		void anzeigen();
    		exit(0);
    	}
    	if(Spielfeld[0][2]=='x' && Spielfeld[1][2]=='x' && Spielfeld[2][2]=='x')
    	{
    		cout<<"Spieler 1 hat gewonnen!"<<endl;
    		void anzeigen();
    		exit(0);
    	}
    	if(Spielfeld[0][0]=='x' && Spielfeld[1][1]=='x' && Spielfeld[2][2]=='x')
    	{
    		cout<<"Spieler 1 hat gewonnen!"<<endl;
    		void anzeigen();
    		exit(0);
    	}
    	if(Spielfeld[0][2]=='x' && Spielfeld[1][1]=='x' && Spielfeld[2][0]=='x')
    	{
    		cout<<"Spieler 1 hat gewonnen!"<<endl;
    		void anzeigen();
    		exit(0);
    	}
    }
    
    int main()
    {
            int i;
    	tic_tac_toe tic;
    	while(i=0;i<5;i++)
    	{
    		tic.anzeigen();
    		tic.Spieler1_zug();
    		tic.gewonnen_s1();
    		tic.anzeigen();
    		tic.Spieler2_zug();
    		tic.gewonnen_s2();
    	}
    }
    

    Verbesserungsvorschläge nehm ich gerne an 🙂



  • Ob aus dem Prog noch was wird.... 😃

    1)Plz for(i=0;i<5;i++) statt while(i=0;i<5;i++) und du könntest das i auch im schleifenkopf deklarieren: for(int i=0;i<5;i++)

    2)Ich würde das Reihen Spalten ändern: Reihe ist Vertical Spalte Horizontal

    3)es gibt kein Unentschieden

    4)gebt mal statt ner zahl zB g+ ein



  • ich würde ein array mit 10 elementen nehmen, und das element ann der stelle 0 ungenutzt lassen.
    und zwar in folgender bedeutung:
    789
    456
    123
    das ist zufällig absichtlich auch die anordnung auf dem ziffernblock der tastatur und damit recht benutzerfreundlich.
    linien kann man definieren mit startpunkt und richtung.
    123= 1 1
    456= 4 1
    789= 7 1
    147= 1 3
    258= 2 3
    369= 3 3
    159= 1 4
    357= 3 2
    klingt nach

    bool testeReihe(int farbe,int start,int richtung){
       return feld[start]==farbe && feld[start+richtung]==farbe && feld[start+2*richtung]==farbe;
    }
    bool testeSPielfeld(int farbe){
       if(testeReihe(farbe,4,1)) return true;
    ...
       if(testeReihe(farbe,3,2)) return true;
       return false;
    }
    

    man kann auch die 8 reihendefinitionen in ein array tun und durch das array laufen.

    bool testeReihe(int farbe,int start,int richtung){
       return feld[start]==farbe && feld[start+richtung]==farbe && feld[start+2*richtung]==farbe;
    }
    bool testeSPielfeld(int farbe){
       int start[8]={1,4,7,1,2,3,1,3};
       int richtung[8]={1,1,1,3,3,3,4,2};
       for(int i=0;i<8;++i)
          if(testeReihe(farbe,start[i],richtung[i]) return true;
       return false;
    }
    


  • Gute Idee Volkard. Hab aber keine Zeit gehabt das in meine Version einzubauen...

    #include<iostream>
    #include<iomanip>
    
    using namespace std;
    
    struct feld
    {
       feld(){isEmpty=true;}
       char ch;//Zeichen
       bool isEmpty;
    };
    
    class tic_tac_toe
    {
    private:
        feld Spielfeld[3][3];
    public:
        void zug(char ch);
        void anzeigen();
        bool gewonnen(char ch);
        tic_tac_toe();
        bool unentschieden();
    };
    
    bool tic_tac_toe::unentschieden()
    {
       for(int i=0;i<3;i++)
       {
          for(int j=0;j<3;j++)
          {
             if(Spielfeld[i][j].isEmpty) return false;
          }
       }
       return true;
    }
    
    tic_tac_toe::tic_tac_toe()
    {
        Spielfeld[0][0].ch='.';
        Spielfeld[0][1].ch='.';
        Spielfeld[0][2].ch='.';
        Spielfeld[1][0].ch='.';
        Spielfeld[1][1].ch='.';
        Spielfeld[1][2].ch='.';
        Spielfeld[2][0].ch='.';
        Spielfeld[2][1].ch='.';
        Spielfeld[2][2].ch='.';
    }
    
    void tic_tac_toe::zug(char ch)
    {
        int reihe=0;
        int spalte=0;
        do
        {
           cout<<"Spalte: ";
           cin>>spalte;
           cout<<"Reihe: ";
           cin>>reihe;
        }while(reihe<1 || reihe>3 || spalte<1 || spalte>3 || !Spielfeld[spalte-1][reihe-1].isEmpty);
        Spielfeld[spalte-1][reihe-1].ch=ch;
        Spielfeld[spalte-1][reihe-1].isEmpty=false;
    }
    
    void tic_tac_toe::anzeigen()
    {
        int i;
        int y;
        for(i=0;i<3;i++)
        {
            for(y=0;y<3;y++)
            {
                cout<<setw(2)<<Spielfeld[y][i].ch;
            }
            cout<<"\n\n";
        }
    }
    
    bool tic_tac_toe::gewonnen(char ch)
    {
        if(Spielfeld[0][0].ch==ch && Spielfeld[0][1].ch==ch && Spielfeld[0][2].ch==ch)
        {
            return true;
        }
        if(Spielfeld[1][0].ch==ch && Spielfeld[1][1].ch==ch && Spielfeld[1][2].ch==ch)
        {
            return true;        
        }
        if(Spielfeld[2][0].ch==ch && Spielfeld[2][1].ch==ch && Spielfeld[2][2].ch==ch)
        {
            return true;        
        }
        if(Spielfeld[0][1].ch==ch && Spielfeld[1][1].ch==ch && Spielfeld[2][1].ch==ch)
        {
            return true;       
        }
        if(Spielfeld[0][0].ch==ch && Spielfeld[1][0].ch==ch && Spielfeld[2][0].ch==ch)
        {
            return true;        
        }
        if(Spielfeld[0][2].ch==ch && Spielfeld[1][2].ch==ch && Spielfeld[2][2].ch==ch)
        {
           return true;       
        }
        if(Spielfeld[0][0].ch==ch && Spielfeld[1][1].ch==ch && Spielfeld[2][2].ch==ch)
        {
           return true;        
        }
        if(Spielfeld[0][2].ch==ch && Spielfeld[1][1].ch==ch && Spielfeld[2][0].ch==ch)
        {
           return true;        
        }
        return false;
    }
    
    int main()
    {
        tic_tac_toe tic;
        while(true)
        {
            tic.anzeigen();
            tic.zug('x');
            if(tic.gewonnen('x'))
            {
                cout<<"Spieler 1 hat gewonnen!"<<endl;
                void anzeigen();
                break;
            }
            if(tic.unentschieden())
            {
                cout<<"Unentschieden!"<<endl;
                void anzeigen();
                break;
            }
    
            tic.anzeigen();
            tic.zug('o');
            if(tic.gewonnen('o'))
            {
                cout<<"Spieler 2 hat gewonnen!"<<endl;
                void anzeigen();
                break;
            }
            if(tic.unentschieden())
            {
                cout<<"Unentschieden!"<<endl;
                void anzeigen();
                break;
            }
    
        }
        cin.ignore();
        getchar();
        return 0;
    }
    


  • ein paar gedanken dazu, die meisten sicherlich schlecht. es geht nur ums ausloten.

    #include<iostream>
    #include<iomanip>
    
    using namespace std;
    
    struct feld
    {
       feld(){isEmpty=true;}
       char ch;//Zeichen
       bool isEmpty;
    };
    //ch überladen und dreiwertig machen
    /*struct feld
    {
       feld(){ch='.';)
       char ch;
    };*/
    
    class tic_tac_toe
    {
    private:
        feld Spielfeld[3][3];//andere anordnung, wie bereits gesagt
    //    int anzahl;
    public:
        void zug(char ch);
        void anzeigen();
        bool gewonnen(char ch);
        tic_tac_toe();
        bool unentschieden();
    };
    
    bool tic_tac_toe::unentschieden()
    {
       //return anzahl==9
       for(int i=0;i<3;i++)
       {
          for(int j=0;j<3;j++)
          {
             if(Spielfeld[i][j].isEmpty) return false;
          }
       }
       return true;
    }
    
    tic_tac_toe::tic_tac_toe()
    {
    //passiert schon im ctor von feld
        Spielfeld[0][0].ch='.';
        Spielfeld[0][1].ch='.';
        Spielfeld[0][2].ch='.';
        Spielfeld[1][0].ch='.';
        Spielfeld[1][1].ch='.';
        Spielfeld[1][2].ch='.';
        Spielfeld[2][0].ch='.';
        Spielfeld[2][1].ch='.';
        Spielfeld[2][2].ch='.';
    }
    
    //bool range(int min,int x,int max){return min<=x && x<=max)
    
    void tic_tac_toe::zug(char ch)
    {
        int reihe=0;
        int spalte=0;
        do
        {
           cout<<"Spalte: ";
           cin>>spalte;
           cout<<"Reihe: ";
           cin>>reihe;
        }while(reihe<1 || reihe>3 || spalte<1 || spalte>3 || !Spielfeld[spalte-1][reihe-1].isEmpty);
    //while(range(1,reihe,3) || range(1,spalte,3) || Spielfeld[spalte-1][reihe-1]!='.');
        Spielfeld[spalte-1][reihe-1].ch=ch;
    //weg    Spielfeld[spalte-1][reihe-1].isEmpty=false;
    //++anzahl
    }
    
    void tic_tac_toe::anzeigen()
    {
    //    int i;
    //    int y;
        for(/*int */i=0;i<3;i++)//besser x?
        {
            for(/*int */y=0;y<3;y++)
            {
                cout<<setw(2)<<Spielfeld[y][i].ch;
            }
            cout<<"\n\n";
        }
    }
    
    bool tic_tac_toe::gewonnen(char ch)
    {//einfacher machen, das return ist viel guter als exit
        if(Spielfeld[0][0].ch==ch && Spielfeld[0][1].ch==ch && Spielfeld[0][2].ch==ch)
        {
            return true;
        }
        if(Spielfeld[1][0].ch==ch && Spielfeld[1][1].ch==ch && Spielfeld[1][2].ch==ch)
        {
            return true;        
        }
        if(Spielfeld[2][0].ch==ch && Spielfeld[2][1].ch==ch && Spielfeld[2][2].ch==ch)
        {
            return true;        
        }
        if(Spielfeld[0][1].ch==ch && Spielfeld[1][1].ch==ch && Spielfeld[2][1].ch==ch)
        {
            return true;       
        }
        if(Spielfeld[0][0].ch==ch && Spielfeld[1][0].ch==ch && Spielfeld[2][0].ch==ch)
        {
            return true;        
        }
        if(Spielfeld[0][2].ch==ch && Spielfeld[1][2].ch==ch && Spielfeld[2][2].ch==ch)
        {
           return true;       
        }
        if(Spielfeld[0][0].ch==ch && Spielfeld[1][1].ch==ch && Spielfeld[2][2].ch==ch)
        {
           return true;        
        }
        if(Spielfeld[0][2].ch==ch && Spielfeld[1][1].ch==ch && Spielfeld[2][0].ch==ch)
        {
           return true;        
        }
        return false;
    }
    
    int main()
    {
        tic_tac_toe tic;
        while(true)//for(;;)
        {
            tic.anzeigen();
            tic.zug('x');
            if(tic.gewonnen('x'))
            {
                cout<<"Spieler 1 hat gewonnen!"<<endl;
    //wirkungslos             void anzeigen();
                break;
    //return statt break, also diese schleife aus der main() raus
            }
            if(tic.unentschieden())
            {
                cout<<"Unentschieden!"<<endl;
                void anzeigen();
                break;
            }
    
            tic.anzeigen();
            tic.zug('o');
            if(tic.gewonnen('o'))
            {
                cout<<"Spieler 2 hat gewonnen!"<<endl;
                void anzeigen();
                break;
            }
            if(tic.unentschieden())
            {
                cout<<"Unentschieden!"<<endl;
                void anzeigen();
                break;
            }
    
        }
        cin.ignore();
        getchar();
        return 0;
    }
    


  • Warum for(;;) statt while(true) ???

    Sonst ja ok man konnte es noch verbessern. Wir könnten für ch auch ein enum machen zb: enum eCh{X,O,no};
    aber ist dann geschmakssache



  • Dumme Smileys meinte for( ; ; )



  • Karldin schrieb:

    Warum for(;;) statt while(true) ???

    for(;;) 🙂 nur um zu zeigen, daß man nicht pascal schreibt.

    Wir könnten für ch auch ein enum machen zb: enum eCh{X,O,no};

    oder char const KREUZ='X'; char const KREIS='O'; char const LEER=' ';
    sowas war ganz fein in nem 4-gewinnt-spiel, das ich mal schrieb.


Anmelden zum Antworten