TicTacToe -- Hilfe?



  • Ich möchte anfangen zu programmieren, da wir in meiner Schule auch programmieren lernen. Allerdings scheitere ich jetzt schon am ersten Projekt "TicTacToe" schon heftig. Hier mal der Code.

    /* 
     * File:   main.cpp
     * Created on 24. Jänner 2011, 23:06
     */
    
    #include <cstdlib>
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <curses.h>
    
    using namespace std;
    
    const int maxfield = 9; 													//Constante für Feld
    char cfield[maxfield] = { '1','2', '3','4','5','6','7','8','9'}; 		   //Feld
    char cselectedfield;													   //welches Feld gewählt wurde
    int nplayerturn = 1; 													  //Wer ist dran?
    bool bgameover = false;													 //spielvorbei
    int nwinner = 0; 														//wer gewinnt (1=player1, 2=player2, 3=unentschieden)
    
    void drawfield (void); 													//zeichnet ein feld
    void drawspace (void);												 	//rückt das feld 20 mal ein
    void checkforwinner (void); 											//prüft wer der gewinner ist
    void saywinner(void); 													//ausgabegewinner
    
    int main(int argc, char** argv) 
    {
    
        char cselector = 'X';
    
            do {
    
                if (nplayerturn == 1)
                {
                    cselector = 'X';
                }
                else
                {
                    cselector = 'O';
                }
    
    			clear();
    
                drawfield();
    
                std::cout << "Spieler " << nplayerturn << " geben Sie bitte eine Feldnummer ein: " << std::endl;
                cselectedfield = cin.get();
    
                cfield[cselectedfield--] = cselector;
    
                checkforwinner();
    
                saywinner();
    
                nplayerturn++;
    
                if (nplayerturn > 2)
                {
                nplayerturn = 1;
                }
    
            } while ( !bgameover);
    }
    
    void drawspace (void)
    {
        for (int i = 0; i <= 20; i++)
        {
            cout << " ";
        }
    }
    
    void drawfield ( void )
    {
    drawspace();
    cout << cfield[0]  << "|"  << cfield[1]  << "|" <<  cfield[2] << endl;
    drawspace();
    cout << "-" << "+" << "-" << "+" << "-" << endl;
    drawspace();
    cout << cfield[3]  << "|"  << cfield[4]  << "|" <<  cfield[5] << endl;
    drawspace();
    cout << "-" << "+" << "-" << "+" << "-" << endl;
    drawspace();
    cout << cfield[6]  << "|"  << cfield[7]  << "|" <<  cfield[8] << endl;
    
    }
    
    void checkforwinner (void)
    {
    	//oben
    	if ( cfield[0] ==  cfield[1] && cfield[1] == cfield[2] && cfield[2] == cfield[0])
    	{
    			nwinner = nplayerturn;
    			bgameover = true;
    	}
    	//mitte
    	else if (cfield[3] ==  cfield[4] && cfield[4] == cfield[5] && cfield[5] == cfield[3])
    	{
    			nwinner = nplayerturn;
    			bgameover = true;
    	}
    	//unten
    	else if (cfield[6] ==  cfield[7] && cfield[7] == cfield[8] && cfield[8] == cfield[6])
    	{
    			nwinner = nplayerturn;
    			bgameover = true;
    	}
    
    	//links
    	else if (cfield[0] ==  cfield[3] && cfield[3] == cfield[6] && cfield[6] == cfield[0])
    	{
    			nwinner = nplayerturn;
    			bgameover = true;
    	}
    	//mitte
    	else if (cfield[1] ==  cfield[4] && cfield[4] == cfield[7] && cfield[7] == cfield[1])
    	{
    			nwinner = nplayerturn;
    			bgameover = true;
    	}
    	//rechts
    	else if ( cfield[2] ==  cfield[5] && cfield[5] == cfield[8] && cfield[8] == cfield[2])
    	{
    			nwinner = nplayerturn;
    			bgameover = true;
    	}
    
    	//Schräg von links oben
    	else if (cfield[0] ==  cfield[4] && cfield[4] == cfield[8] && cfield[8] == cfield[0])
    	{
    			nwinner = nplayerturn;
    			bgameover = true;
    	}
    	//Schräg von rechts oben
    	else if ( cfield[2] ==  cfield[4] && cfield[4] == cfield[6] && cfield[6] == cfield[0])
    	{
    			nwinner = nplayerturn;
    			bgameover = true;
    	}
    
    }
    
    void saywinner (void)
    {
    	if (nwinner == 1)
    	{
    		std::cout << "Glückwunsch, der Gewinner ist Spieler " << nplayerturn << std::endl;
    	}
    	else	if (nwinner == 2)
    	{
    		std::cout << "Glückwunsch, der Gewinner ist Spieler " << nplayerturn << std::endl;
    	}
    	else	if (nwinner == 3)
    	{
    		std::cout << "Schade es steht unentschieden" << std::endl;
    	}
    
    }
    

    Ich benutze Ubuntu 10.10.Ich weiß das Spiel ist noch nicht vollständig (Überprüfung von der Eingabe fehlt usw.), allerdings möchte ich zuerst dass das Grundlegende funktioniert.Und welche Entwicklungsumgebung würdet Ihr mir empfehlen?

    Danke & mfg

    Kuwiano



  • Wo ist hier was Linux/Unix spezifisches (falsches Forum)? Viel wichtiger ist jedoch, was funktioniert denn nicht? Wir raten und suchen ungerne.

    Ich würde g++ verwenden.



  • Sry das hab ich ganz vergessen - Wenn ich das Programm ausführe (mit g++) dan stehen anstatt Zahlen seltsame zeichen dort und wenn ich eine Zahl drücke wird diese nicht mit O und X überschrieben sondern es passiert einfach nichts.



  • Du hast wenige kleine Fehler:

    1. mache aus cselectedfield ein:

    int cselectedfield;
    

    2. entferne alle unbenötigten includes (also alles außer iostream und den für clear()
    3. ändere die Inkrementation auf preincrement oder mach einfach "-1"

    cfield[--cselectedfield] = cselector;
    

    4. verwende

    std::cin >> cselectedfield;
    

    anstelle von cin.get()



  • Wow, danke für die schnelle Antwort! Es funktioniert jetzt alles, muss nur noch die Fehlerüberprüfung machen. DANKE!

    mfg



  • Ich habe jetzt eine Fehlerüberprüfung eingebaut und Sie funktioniert nicht. Starte ich das Programm, steht in der Konsole nur Speicherzugriffsfehler hier der veränderte Code:

    int cselectedfield = 1;
    
    while(!bError(cselectedfield))
    			{
    			//Eingabeaufforderung
                std::cout << "Spieler " << nplayerturn << " geben Sie bitte eine Feldnummer ein: " << std::endl;
                std::cin >> cselectedfield;
    			}
    
    bool bError (int cselectedfield)
    {
    	bool berror = false;
    
    	//Ist die Eingegeben Zahl zw. 1-9?
    	if (cselectedfield != '1' ||cselectedfield != '2' ||cselectedfield != '3' ||
    	    cselectedfield != '4' ||cselectedfield != '5' ||cselectedfield != '6' ||
    	    cselectedfield != '7' ||cselectedfield != '8' ||cselectedfield != '9')
    	{
    		berror = true;
    		std::cout << "Ungültige Eingabe" << std::endl;
    	}
    
    	return berror;
    }
    

    Entschuldige für falsches Forum 😞 könnt ihr ihn ins richtige verschieben?



  • Warum übergibst du der Fuktion eine globale Variable? Die Variable ist nun ein int und kein Char, warum prüfst du nicht auf Zahlen anstatt auf Zeichen z.B.

    if (cselectedfield < 1 || cselectedfield > 9)
    

    Sollte es nicht so lauten?

    while(bError(cselectedfield)
    

    Sollte der Initialwert nicht cselectedfield = 0 sein, ansonsten würde ich die eine do-while Schleife ans Herz legen.



  • Gut, ich habe dass jetzt mit einer Do-While Schleife gemacht und funktioniert nur wie baue ich jetzt eine überprüfung ein die Prüft ob das Feld schon belegt ist? Ich habe es zwar versucht allerdings verhält sich dann mein gesammten Spiel sehr seltsam + es funktioniert nicht. Auch das mit der Globalen Variable hab ich ausgebessert -> Danke für den Hinweis ist mir gar nicht aufgefallen.

    else if (cfield[--iselectedfield] == 'X' || cfield[--iselectedfield] == 'O')
    	{
    		berror = true;
    		cout << "Ungültige Eingabe" << endl;
    	}
    


  • Noch ein Tipp lasse die ungarische Notation weg, ist viel Aufwand für nichts. Zu dem Problem: "Was denkst du macht --?" Es verändert die Variable! Lasse es weg und sieh was passiert.

    Wenn cfield[6] selektiert ist ergibt die Abfrage mit dem Dekrement wenig Sinn:

    if(cfield[5] == 'X' || cfield[4] == 'O') //....
    


  • Ich sehe hier nichts Unix-spezifisches. curses benutzt Du soweit ich sehen kann ja auch nirgends, bzw. wenn doch, nimmt es keine zentrale Rolel in Deinem Programm ein.

    Ich verschiebe Dich mal ins C++-Forum.



  • Dieser Thread wurde von Moderator/in nman aus dem Forum Linux/Unix in das Forum C++ (auch C++0x) verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Ich habe alles angepasst was Ihr mir gesagt habt und veränder Hier nochmal der gesamte Code:

    /* 
     * File:   main.cpp
     * Created on 24. Jänner 2011, 23:06
     */
    
    #include <iostream>
    #include <stdlib.h>
    #include <string.h>
    
    using namespace std;
    
    const int maxfield = 9; 													//Constante für Feld
    char cfield[maxfield] = { '1','2', '3','4','5','6','7','8','9'}; 		   //Feld
    int iselectedfield;													  		//welches Feld gewählt wurde
    int nplayerturn = 1; 													  //Wer ist dran?
    bool bgameover = false;													 //spielvorbei
    int nwinner = 0; 														//wer gewinnt (1=player1, 2=player2, 3=unentschieden)
    
    bool bError ();
    void drawfield (void); 													//zeichnet ein feld
    void drawspace (void);												 	//rückt das feld 20 mal ein
    void checkforwinner (void); 											//prüft wer der gewinner ist
    void saywinner(void); 													//ausgabegewinner
    
    int main(int argc, char** argv) 
    {
    
        char cselector = 'X';
    
            do {
    
    			//X oder O setzen 
                if (nplayerturn == 1)
                {
                    cselector = 'X';
                }
                else
                {
                    cselector = 'O';
                }
    
    			//vorherigen Konsolenoutput löschen | Spielfeld Zeichnen
    			system("clear");
    
                drawfield();
    
    			do{				
    			//Eingabeaufforderung
                std::cout << "Spieler " << nplayerturn << " geben Sie bitte eine Feldnummer ein: " << std::endl;
                std::cin >> iselectedfield;
    			}while(bError());
    
    			//Feld ändern - X oder O
                cfield[--iselectedfield] = cselector;
    
    			// vorherigen Konseloutput löschen | Feld Aktualisieren
    			system("clear");
    
                drawfield();
    
    			//Prüfen ob es einen Gewinner gibt & diesen verkünden
                checkforwinner();
    
                saywinner();
    
    			//Nächster Spieler ist dran
                nplayerturn++;
    
                if (nplayerturn > 2)
                {
                nplayerturn = 1;
                }
    
            } while ( !bgameover);
    }
    
    bool bError (void)
    {
    	bool berror = false;
    	//int ibackupselectedfield;
    
    	//Ist die Eingegeben Zahl zw. 1-9?
    	if (iselectedfield < 1 || iselectedfield > 9) 
    	{
    		berror = true;
    		cout << "Ungültige Eingabe" << endl;	
    	}
    
    	else if (cfield[--iselectedfield] == 'X' || cfield[--iselectedfield] == 'O')
    	{	
    		berror = true;
    		cout << "Ungültige Eingabe" << endl;
    	}
    
    	return berror;
    }
    
    // Spielfeld Einrücken um 20 spaces
    void drawspace (void)
    {
        for (int i = 0; i <= 20; i++)
        {
            cout << " ";
        }
    }
    
    //Spielfeld zeichne
    void drawfield ( void )
    {
    drawspace();
    cout << cfield[0]  << "|"  << cfield[1]  << "|" <<  cfield[2] << endl;
    drawspace();
    cout << "-" << "+" << "-" << "+" << "-" << endl;
    drawspace();
    cout << cfield[3]  << "|"  << cfield[4]  << "|" <<  cfield[5] << endl;
    drawspace();
    cout << "-" << "+" << "-" << "+" << "-" << endl;
    drawspace();
    cout << cfield[6]  << "|"  << cfield[7]  << "|" <<  cfield[8] << endl;
    }
    
    //Prüfen Wer gewinnt 
    void checkforwinner (void)
    {
    	//oben
    	if ( cfield[0] ==  cfield[1] && cfield[1] == cfield[2] && cfield[2] == cfield[0])
    	{
    			nwinner = nplayerturn;
    			bgameover = true;
    	}
    	//mitte
    	else if (cfield[3] ==  cfield[4] && cfield[4] == cfield[5] && cfield[5] == cfield[3])
    	{
    			nwinner = nplayerturn;
    			bgameover = true;
    	}
    	//unten
    	else if (cfield[6] ==  cfield[7] && cfield[7] == cfield[8] && cfield[8] == cfield[6])
    	{
    			nwinner = nplayerturn;
    			bgameover = true;
    	}
    
    	//links
    	else if (cfield[0] ==  cfield[3] && cfield[3] == cfield[6] && cfield[6] == cfield[0])
    	{
    			nwinner = nplayerturn;
    			bgameover = true;
    	}
    	//mitte
    	else if (cfield[1] ==  cfield[4] && cfield[4] == cfield[7] && cfield[7] == cfield[1])
    	{
    			nwinner = nplayerturn;
    			bgameover = true;
    	}
    	//rechts
    	else if ( cfield[2] ==  cfield[5] && cfield[5] == cfield[8] && cfield[8] == cfield[2])
    	{
    			nwinner = nplayerturn;
    			bgameover = true;
    	}
    
    	//Schräg von links oben
    	else if (cfield[0] ==  cfield[4] && cfield[4] == cfield[8] && cfield[8] == cfield[0])
    	{
    			nwinner = nplayerturn;
    			bgameover = true;
    	}
    	//Schräg von rechts oben
    	else if ( cfield[2] ==  cfield[4] && cfield[4] == cfield[6] && cfield[6] == cfield[0])
    	{
    			nwinner = nplayerturn;
    			bgameover = true;
    	}
    
    	//unentschieden
    	else if ((cfield[0] !='1' && cfield[1] != '2' && cfield[2] !='3') &&
    			 (cfield[3] !='4' && cfield[4] != '5' && cfield[5] !='6') &&
    		     (cfield[6] !='7' && cfield[7] != '8' && cfield[8] !='9'))
    	{
    			nwinner = 3;
    			bgameover = true;
    	}
    
    }
    
    //verkündet den Gewinner
    void saywinner (void)
    {
    	if (nwinner == 1)
    	{
    		std::cout << "Glückwunsch, der Gewinner ist Spieler " << nplayerturn << std::endl;
    	}
    	else	if (nwinner == 2)
    	{
    		std::cout << "Glückwunsch, der Gewinner ist Spieler " << nplayerturn << std::endl;
    	}
    	else	if (nwinner == 3)
    	{
    		std::cout << "Schade es steht unentschieden" << std::endl;
    	}
    
    }
    

    Das Spiel funktioniert allerdings: wenn ich z.B.: 3 eingebe ändert sich das Feld 2 O.o.



  • Ein kleines Update: Ich benutzte jetzt Code::Blocks mit gcc compiler und es funktioniert toll mit einer Ausnahme: system("clear"); funktioniert nicht mehr :/. Irgendwelche Lösungen?


  • Mod

    Kuwiano schrieb:

    Ein kleines Update: Ich benutzte jetzt Code::Blocks mit gcc compiler und es funktioniert toll mit einer Ausnahme: system("clear"); funktioniert nicht mehr :/. Irgendwelche Lösungen?

    Definiere "funktioniert nicht mehr".



  • Nach dem ich jetzt mal das Programm gestartet habe (außerhalb Code::Blocks) funktz wider dafür hab ich 1 Problem (hoffentlich das Letzte! Gebe ich einen Char ein ("a") dann hängt sich das Programm auf und gibt Hundert mal de selbe Line aus (Bitte Geben Sie eine Zahl ein: ). Hört erst auf wenn Ich das Terminal schließe.



  • Das liegt daran, weil ein falsches Zeichen (keine Zahl wie int ja erwartet) eingegeben wurde und bei cin nun der Fehlerstatus verhängt ist. Das kannst du so lösen:

    #include <limits>
    if( !(std::cin >> variable) ) {
    	std::cin.clear(); //fehlerstatus zurücksetzen
    	std::cin.ignore(std::numeric_limits<int>::max(), '\n'); //fehlerhafte Zeichen überspringen
        continue; //oder sowas in der richtung
    }
    

    Dann sollte alles weitergehen.



  • Hey!

    Vielen Dank jetzt funktioniert alles allerdings durchschaue ich den letzten Teil nicht ganz 😞 --> und ich will das verstehen was ich programmiere :D.

    std::cin.ignore(std::numeric_limits<int>::max(), '\n'); //fehlerhafte Zeichen überspringen
    

    Was bringt das ganze/was heißt std::numeric_limits<int>::max(), ?

    Danke für eure Hilfe



  • numeric_limits<DATENTYP>::max()/min() gibt die jeweilige größtmögliche/kleinstmögliche Zahl für den Datentyp an. Was std::cin.ignore() macht, erfährst du hier.

    mfg



  • Ok cin.ignore() hab ich verstanden und auch die Überprüfung ist logisch allerdings verwirrt mich das Dritte:

    std::cin.ignore(std::numeric_limits<int>::max(), '\n'); //fehlerhafte Zeichen überspringen
    

    Soweit ich das verstehen könnte ich auch genauso gut:

    iselectedfield = 11;
    

    damit wäre der Fehler doch genauso ausgewiesen?!? Oder verstehe ich da etwas falsch?



  • Wenn du eine Variable vom Typ int hast und sie vom Standardeingabemedium eingeben lässt, werden die eingegeben Zeichen im Puffer gespeichert. Wenn also statt einer Zahl ein Buchstabe o.ä. eingegeben wird, dann hängen die Zeichen im Speicher rum. Du kannst dann solange den Fehlerstatus mit clear() auf 0 setzen wie du willst - durch die Zeichen, die immer noch da sind, wird er jedes mal aufs neue verhängt. Wenn du allerdings mit ignore() jedes fehlerhafte Zeichen aus dem Puffer "verwirfst", dann sind keine fehlerhaften Zeichen mehr im Puffer und der Fehlerstatus wird erfolgreich dauerhaft auf 0 gesetzt - jetzt kann wieder eingegeben werden.
    Wenn ich was falsches gesagt habt korrigiert mich bitte, ich kenn mich da nicht so gut aus.


Anmelden zum Antworten