Thread: TicTacToe

  1. #1
    Registered Abuser Loic's Avatar
    Join Date
    Mar 2007
    Location
    Sydney
    Posts
    115

    TicTacToe

    Hi everyone!
    I just finished writing up the main program logic for a tictactoe game and it's all working fine but half way though a game it will just exit, it will do so at a diffrent point in the game each time i play it...

    i think it may be a bug in the checkwin function, but i cant see anything wrong in there...

    or have i made a stupid logic error somewhere? please help
    Code:
    #include <cstdlib>
    #include <iostream>
    
    using namespace std;
    char sqr[3][3];
    struct player { string name; char syb; };
    struct player play[2];
    /*---------------------------------*/
    void ai(void);
    void cou(void);
    void turn(void);
    void checkwin(void);
    void humanVcpu(void);
    /*---------------------------------*/
    int main()
    {
        system("cls");
        humanVcpu();
        system("PAUSE");
        return EXIT_SUCCESS;
    }
    void humanVcpu(void)
    {
         play[1].name = "CPU";
         cout << "Please enter your name >>"; cin >> play[0].name;
         play[0].syb = 'X';
         play[1].syb = 'O';
         turn();
    }
    void turn(void)
    {
         cou();int x,y;
         cout << "Row: "; cin >> x;
         cout << "Column: "; cin >> y;
         sqr[x-1][y-1] = play[0].syb;
         checkwin();
         ai();
    }
    void cou(void)
    {
         system("cls");
         cout<<"\n\t\t                1   2   3\n"<<endl;
         cout<<"\t\t             1  "<<sqr[0][0]<<" | "<<sqr[0][1]<<" | "<<sqr[0][2]<<endl;
         cout<<"\t\t               ---|---|---\n";
         cout<<"\t\t             2  "<<sqr[1][0]<<" | "<<sqr[1][1]<<" | "<<sqr[1][2]<<endl;
         cout<<"\t\t               ---|---|---\n";
         cout<<"\t\t             3  "<<sqr[2][0]<<" | "<<sqr[2][1]<<" | "<<sqr[2][2]<<"\n\n\n";
    }
    void checkwin(void)
    {
         // check if human win
         // - wins
         for (int i=0;i<3;i++)
             if ((sqr[i][0]==play[0].syb)&&(sqr[i][1]==play[0].syb)&&(sqr[i][2]==play[0].syb)) {
                cout<<play[0].name<<" wins!";system("pause"); }
         // | wins
         for (int i=0;i<3;i++)
             if ((sqr[0][i]==play[0].syb)&&(sqr[1][i]==play[0].syb)&&(sqr[2][i]==play[0].syb)) {
                cout<<play[0].name<<" wins!";system("pause"); }
         // / wins
         if ((sqr[0][0]==play[0].syb)&&(sqr[1][1]==play[0].syb)&&(sqr[2][2]==play[0].syb)) {
                cout<<play[0].name<<" wins!";system("pause"); }
         // \ wins
         if ((sqr[2][0]==play[0].syb)&&(sqr[1][1]==play[0].syb)&&(sqr[0][2]==play[0].syb)) {
                cout<<play[0].name<<" wins!";system("pause"); }
         // check if cpu win
         for (int i=0;i<3;i++)
             if ((sqr[i][0]==play[1].syb)&&(sqr[i][1]==play[1].syb)&&(sqr[i][2]==play[1].syb)) {
                cout<<play[1].name<<" wins!";system("pause"); }
         // | wins
         for (int i=0;i<3;i++)
             if ((sqr[0][i]==play[1].syb)&&(sqr[1][i]==play[1].syb)&&(sqr[2][i]==play[1].syb)) {
                cout<<play[1].name<<" wins!";system("pause"); }
         // / wins
         if ((sqr[0][0]==play[1].syb)&&(sqr[1][1]==play[1].syb)&&(sqr[2][2]==play[1].syb)) {
                cout<<play[1].name<<" wins!";system("pause"); }
         // \ wins
         if ((sqr[2][0]==play[1].syb)&&(sqr[1][1]==play[1].syb)&&(sqr[0][2]==play[1].syb)) {
                cout<<play[1].name<<" wins!";system("pause"); }     
    }
    void ai(void)
    {
         // - wins
         for (int i=0;i<3;i++) {
             if ((sqr[i][0]!=play[0].syb)&&(sqr[i][0]!=play[1].syb))
                      if ((sqr[i][1]==play[0].syb)&&(sqr[i][2]==play[0].syb)){sqr[i][0]=play[1].syb;return;}
             if ((sqr[i][1]!=play[0].syb)&&(sqr[i][1]!=play[1].syb))
                      if ((sqr[i][0]==play[0].syb)&&(sqr[i][2]==play[0].syb)){sqr[i][1]=play[1].syb;return;}
             if ((sqr[i][2]!=play[0].syb)&&(sqr[i][2]!=play[1].syb))
                      if ((sqr[i][0]==play[0].syb)&&(sqr[i][1]==play[0].syb)){sqr[i][2]=play[1].syb;return;}}
         // | wins
         for (int i=0;i<3;i++) {
             if ((sqr[0][i]!=play[1].syb)&&(sqr[0][i]!=play[1].syb))
                      if ((sqr[1][i]==play[0].syb)&&(sqr[2][i]==play[0].syb)){sqr[0][i]=play[1].syb;return;}}
         // \ wins
         if ((sqr[0][0]!=play[0].syb)&&(sqr[0][0]!=play[1].syb))
            if ((sqr[1][1]==play[0].syb)&&(sqr[2][2]==play[0].syb)){sqr[0][0]=play[1].syb;return;}
         if ((sqr[1][1]!=play[0].syb)&&(sqr[1][1]!=play[1].syb))
            if ((sqr[0][0]==play[0].syb)&&(sqr[2][2]==play[0].syb)){sqr[1][1]=play[1].syb;return;}
         if ((sqr[2][2]!=play[0].syb)&&(sqr[2][2]!=play[1].syb))
            if ((sqr[0][0]==play[0].syb)&&(sqr[1][1]==play[0].syb)){sqr[2][2]=play[1].syb;return;}
         // / wins
         if ((sqr[0][2]!=play[0].syb)&&(sqr[0][2]!=play[1].syb))
            if ((sqr[1][1]==play[0].syb)&&(sqr[2][0]==play[0].syb)){sqr[0][2]=play[1].syb;return;}
         if ((sqr[1][1]!=play[0].syb)&&(sqr[1][1]!=play[1].syb))
            if ((sqr[2][0]==play[0].syb)&&(sqr[0][2]==play[0].syb)){sqr[1][1]=play[1].syb;return;}
         if ((sqr[2][0]!=play[0].syb)&&(sqr[2][0]!=play[1].syb))
            if ((sqr[0][2]==play[0].syb)&&(sqr[1][1]==play[0].syb)){sqr[2][0]=play[1].syb;return;}
         // if no winning sqr, pick random.
         srand ( time(NULL) );
         int rndA, rndB;
         for (;;){
         rndA = rand()%3; rndB = rand()%3;
         if ((sqr[rndA][rndB]!=play[0].syb)&&(sqr[rndA][rndB]!=play[1].syb)){sqr[rndA][rndB]=play[1].syb;break;}}
         turn();
    }

  2. #2
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    srand() is supposed to only be called once during the execution of a program. You should call it at the beginning of main(), or perhaps humanVcpu() or cou().

    Your checkwin() function could be greatly simplified. First of all, you have a bunch of code which checks if the human wins, and then a bunch of nearly identical code which checks if the computer wins. You could use something like
    Code:
         // check if human win
         // - wins
         for (int i=0;i<3;i++)
             if ((sqr[i][0]==play[player].syb)&&(sqr[i][1]==play[player].syb)&&(sqr[i][2]==play[player].syb)) {
                cout<<play[0].name<<" wins!";system("pause"); }
    and set player to 0 and 1, perhaps by putting that code into a function and calling the function twice, or with a for loop.

    I'll use this same code as an example.
    Code:
         // - wins
         for (int i=0;i<3;i++)
             if ((sqr[i][0]==play[0].syb)&&(sqr[i][1]==play[0].syb)&&(sqr[i][2]==play[0].syb)) {
                cout<<play[0].name<<" wins!";system("pause"); }
    It seems that you could make use of another nested loop there. Something like (I'll try to fix your indentation)
    Code:
         // - wins
        for (int i = 0; i < 3; i ++) {
            int j;
            for (j = 0; j < 3; j ++) {
                if (sqr[i][j] != play[0].syb) break;
            }
            if(j == 3) { /* wins */ }
        }
    Just a thought.

    Also:
    Code:
         // / wins
         if ((sqr[0][0]==play[0].syb)&&(sqr[1][1]==play[0].syb)&&(sqr[2][2]==play[0].syb)) {
                cout<<play[0].name<<" wins!";system("pause"); }
         // \ wins
         if ((sqr[2][0]==play[0].syb)&&(sqr[1][1]==play[0].syb)&&(sqr[0][2]==play[0].syb)) {
                cout<<play[0].name<<" wins!";system("pause"); }
    I think you got those comments mixed up.

    Also, your game is an infinite loop -- whenever the game is supposed to end, you print a message etc but the game doesn't exit.

    And note that when your program prompts you for the row and column, you have to enter 1-3, not 0-2.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. TicTacToe AI
    By Loic in forum C++ Programming
    Replies: 9
    Last Post: 05-28-2007, 01:37 PM
  2. C++ Tictactoe
    By vinter in forum C++ Programming
    Replies: 6
    Last Post: 04-03-2007, 09:56 PM
  3. tictactoe symbol entering problem
    By ademkiv in forum C Programming
    Replies: 1
    Last Post: 03-21-2006, 11:53 AM
  4. Tictactoe problem
    By endo in forum Windows Programming
    Replies: 3
    Last Post: 04-10-2005, 09:36 AM
  5. TicTacToe OOP
    By NickESP in forum C++ Programming
    Replies: 4
    Last Post: 02-07-2003, 11:47 AM