I recently wrote a program to generate a tic tac toe game. The program should ask the user to select a number from the 'selection board', and this number will correspond to a spot on the game board. The user is playing against him/herself. I've encountered a pretty glaring bug that I can't seem to fix, though. Every time I enter a designated number it outputs "That spot on the board is taken," even when it is not. Can anyone help me with this? I suspect it's just something small that I missed.

//Tic Tac Toe game

#include <iostream>
using namespace std;

 //note: main program placed below function definitions for convenience

int game[9]={1,2,3,4,5,6,7,8,9}; //declares an array for the game board

/////////////////////////////////
//Part 1: Function Definitions//
///////////////////////////////

void TicTacToe() //makes a function for the selection board
{
    cout<<"This is the selection board:"<<endl;
    cout<<"-----"<<endl;
    cout<<"1|2|3"<<endl;
    cout<<"-----"<<endl;
    cout<<"4|5|6"<<endl;
    cout<<"-----"<<endl;
    cout<<"7|8|9"<<endl;
    cout<<"-----"<<endl;
}

int move(int play,int turn) //puts player's turn in memory
{
    game[turn-1]=play;
    if (turn==1)
       return play+1;
    else if (turn==2)
       return play-1;
}

int state(int play,int first)
{
   if((game[1]&&game[2]&&game[3]==play)||(game[1]&&game[4]&&game[7]==play)||(game[1]&&game[5]&&game[9]==play))
        return play;
    else if ((game[2]&&game[5]&&game[8]==play)||(game[3]&&game[5]&&game[7]==play)||(game[3]&&game[6]&&game[9]==play))
        return play;
    else if ((game[4]&&game[5]&&game[6]==play)||(game[7]&&game[8]&&game[9]== play))
        return play;
}  

void outputBoard() //outputs current state of board
{
    for(int x=1;x<=9;x++) //makes a loop for each turn -- x and o
    {
        if (game[x-1]==1)
            cout<<"x";
        else if (game[x-1]==2)
            cout<<"o";
        else
            cout<<" ";
        cout <<"|";
        if (x==3||x==6)
            cout<<endl<<"-----"<<endl;
    }
    cout<<endl;
}

/////////////////////////
//Part 2: Main Program//
///////////////////////

int main ()
{
    int won,turn1,turn2,first,move;
    TicTacToe();
    cout<<endl;
    for(int x=1;x<=9;x++) //searches for moves
    { 
      if(first==1)
         cout<<turn1<<endl;
      else if(first==2)
         cout<<turn2<<endl;
    }

    do //assures that each selection is possible
    {
       cout<<"Please select a number from the selection board.";
          cin>>move;
       if(game[move-1]!=0)
          cout << "That spot on the board is taken."<<endl;
       else if(game[move>9])
          cout<<"You cannot select a number over 9."<<endl;
    }
        while (move<1||move>9||game[move-1]!=0);

        first=state(first,move); //calls function with current state of the board
        cout<<endl;
        outputBoard();

        won=state(first,move); //outputs if program finds a winner
        if(won==1)
        {
           cout<<turn2<<"O wins."<<endl;
           break;
        }
        else if(won==2)
        {
          cout<<turn1<<"X wins."<<endl;
          break;
        }
    }
    system ("PAUSE");
    return 0;
}

Edited 3 Years Ago by Reverend Jim: Fixed formatting

I just quickly glanced at your code so please forgive me if this is wrong but don't you initialize the game[] with the values {1,2,3,4,5,6,7,8,9} but then to tell if there is a move there you compare the value at an index with 0? If none of the values equal 0 then it will always return that the space is taken.

Well, I fixed it up a bit. I still have one more problem: After 6 moves, the game declares a winner even if there isn't one. Here is my revised code:

//Tic Tac Toe game

#include <iostream>
using namespace std;

 //note: main program placed below function definitions for convenience

int game[9]; //declares an array for the game board

/////////////////////////////////
//Part 1: Function Definitions//
///////////////////////////////

void TicTacToe() //makes a function for the selection board
{
    cout<<"This is the selection board:"<<endl;
    cout<<"-----"<<endl;
    cout<<"1|2|3"<<endl;
    cout<<"-----"<<endl;
    cout<<"4|5|6"<<endl;
    cout<<"-----"<<endl;
    cout<<"7|8|9"<<endl;
    cout<<"-----"<<endl;
}

int move1(int play,int turn) //puts player's turn in memory
{
    game[turn-1]=play;
    if (play==1)
       return play+1;
    else if (play==2)
       return play-1;
}

int state(int play,int first)
{
   if((game[1]&&game[2]&&game[3]==play)||(game[1]&&game[4]&&game[7]==play)||(game[1]&&game[5]&&game[9]==play))
        return play;
    else if ((game[2]&&game[5]&&game[8]==play)||(game[3]&&game[5]&&game[7]==play)||(game[3]&&game[6]&&game[9]==play))
        return play;
    else if ((game[4]&&game[5]&&game[6]==play)||(game[7]&&game[8]&&game[9]== play))
        return play;
}  

void outputBoard() //outputs current state of board
{
    for(int x=1;x<=9;x++) //makes a loop for each turn -- x and o
    {
        if (game[x-1]==1)
            cout<<"x";
        else if (game[x-1]==2)
            cout<<"o";
        else
            cout<<" ";
        cout <<"|";
        if (x==3||x==6)
            cout<<endl<<"-----"<<endl;
    }
    cout<<endl;
}

/////////////////////////
//Part 2: Main Program//
///////////////////////

int main ()
{
    int won,turn1,turn2,first,move;
    TicTacToe();
    cout<<endl;

     cout<<"Who goes first? X (Player 1) or O (Player 2)?"<<endl;
     cin>>first;
     for(int x=1;x<=9;x++) 
     {

     //  if(first==1)
     //    cout<<turn1<<endl;
     //else if(first==2)
     //    cout<<turn2<<endl;

    do //assures that each selection is possible
    {
       cout<<"Please select a number from the selection board.";
          cin>>move;
       if(game[move-1]!=0)
          cout << "That spot on the board is taken."<<endl;
       else if(move<1 || move>9)
          cout<<"You cannot select a number over 9."<<endl;
    }
        while (move<1||move>9||game[move-1]!=0);

        first=move1(first,move); //calls function with current state of the board
        cout<<endl;
        outputBoard();

        won=state(first,move); //outputs if program finds a winner
        if(won==1)
        {
           cout<<turn2<<"O wins."<<endl;
           break;
        }
        else if(won==2)
        {
          cout<<turn1<<"X wins."<<endl;
          break;
        }
    }
    system ("PAUSE");
    return 0;
}

Edited 3 Years Ago by Reverend Jim: Fixed formatting

is state() supposed to detect winners?

First of all, it does not always return a value.

Secondly the expression game[1]&&game[2]&&game[3]==play does not test positions 1, 2 and 3 for the value play. I think you wanted game[1] == play && game[2] == play && game[3] == play Third, when you declare the board with game[9] the indexes are 0 through 8. There is no 9.

game[1]&&game[2]&&game[3]==play

That's wrong. && can't be chained like some other operators can be. Change it to :

if( (game[1] == play &&
     game[2] == play  &&
     game[3] == play) ||............

thank you all for the help. my original problem has been solved.

but now another problem arises: the program seems to now ignore when X or O wins. It just continues with the loop. any way i can solve this?

Just commenting you can chain them together but you need: if (game[1]&game[2]&game[3])==play) BUT you get away with this because the possible values of game[] are 0,1,2. The above logic will fail if you are not using powers of 2 as the flag values.

Normally, the shorthand version I have written, gives better executions speed. Especially, since compilers are very bad at determining that game[] is binary bound. (and I also think it is almost impossible for a compiler to determine this)

Could you post the new version of state()? (and any other code related to checking for wins?)

Could you post the new version of state()? (and any other code related to checking for wins?)

I didn't change state. Not sure what you were indicating, sorry.

Currently it's:

int state(int play,int first)

And as for detecting wins:

first=move1(first,move); //calls function with current state of the board
        cout<<endl;
        outputBoard();
        
        won=state(first,move); //outputs if program finds a winner
        if(won==1)
        {
           cout<<turn2<<"O wins."<<endl;
           break;
        }
        else if(won==2)
        {
          cout<<turn1<<"X wins."<<endl;
          break;
        }

I wanted to see the body of state(), not the prototype.
State decides who won and was the source of a lot of your bugs earlier...I want to see how you have re-coded it.

Oh. I did it this way:

if((game[1]==play&&game[2]==play&&game[3]==play)||(game[1]==play&&game[4]==play&&game[7]==play)||(game[1]==play&&game[5]==play&&game[9]==play))
        return play;
   else if((game[2]==play&&game[5]==play&&game[8]==play)||(game[3]==play&&game[5]==play&&game[7]==play)||(game[3]==play&&game[6]==play&&game[9]==play))
      return play;
   else if((game[4]==play&&game[5]==play&&game[6]==play)||(game[7]==play&&game[8]==play&&game[9]==play))
      return play;

That still has the range bug in it.

There is no game[9]

the first winning row should be game[0], game[1], game[2]

Also, when you call state() from main(), the value for first (which is the player to move) has already been updated to the player for the next move, but state() is looking to see if that player won. You should call state() with the player that just filled a square.

I also think you should have a return value indicating no win. For example the add the lines:
else
return 999;
As is, there is no valid return value if there is no win, meaning the value assigned to won back in main() could be anything or nothing. My compiler usually returns an error saying not all return paths have a value when I forget to do this.

This article has been dead for over six months. Start a new discussion instead.