• Advertisement
Sign in to follow this  

Checking for a Winner - Tic Tac Toe [SOLVED]

This topic is 4711 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello, I'm fairly new to C++ programming, but know a bit, so I took the advice of the many experienced programs I saw and decided to make a simple game - a console-based Tic Tac Toe in C++. Everything works properly except for detecting whether or not there is a winner, and if there is a winner, who the winner is (X or O). Right now the game is simply 2 player - there is no option to play the computer or AI. Here is the code that I am currently using (unsuccessfully):
bool GameClass::IsWin()
{

if ((board[1][1] == board[1][2] && board[1][2] == board[1][3] && board[1][1]!=' ')||
(board[1][1] == board[2][1] && board[2][1] == board[3][1] && board[1][1]!=' ')||
(board[1][3] == board[2][3] && board[2][3] == board[3][3] && board[1][3]!=' ')||
(board[3][1] == board[3][2] && board[3][2] == board[3][3] && board[3][1]!=' ')||
(board[1][3] == board[2][2] && board[2][2] == board[3][1] && board[1][3]!=' ')||
(board[1][1] == board[2][2] && board[2][2] == board[3][3] && board[1][1]!=' '))
   { 
      GameClass::Winner(); return true;
   }
   else return false;
}


GameClass::Winner() knows which player has just placed a mark on the board, so it can then return a "player ID" (a 1 or 2) as well as setting the boolean value "winner" to "true" which triggers my game loop to break. This is seen here:
void GameLoop(void)
{
     while (!game.IsWin() && game.turns < 10)
     {
           game.PrintBoard();
           game.GetInput();
           if(game.IsSpotTaken(game.row, game.col))
           { game.AlreadyTakenErr(); game.GetInput(); }
           game.PlaceMark(game.row, game.col, game.id);
           game.IsWin();           
     }  
     
     if (game.turns < 10)
     {
        std::cout << "Congratulations to Player " << game.wid << "! You are the winner!\n";
     }
     
     else
     {
         std::cout << std::endl;
         std::cout << "Wow, you both played well. It ended up being a tie!\n";
     }
}


My "game board" is a two-dimensional 3x3 char array (board[3][3];) in which I am only using indices 1, 2, and 3 so that they more accurately correspond to a real-world tic-tac-toe board. I've Googled for various implimentations of an algorithm to check to see if there is a winner and tried various ones, but I have not yet gotten anything to work. Sorry that I am so new at this, but I've worked on it for a couple hours, and I'm pretty sure that I'm stuck. Anyone have some tips or help? Thank you very much. [Edited by - villiageidiot on June 2, 2005 7:27:14 AM]

Share this post


Link to post
Share on other sites
Advertisement
if you have something like this:

a b c
. _________
1 |__|__|__|
2 |__|__|__|
3 |__|__|__|

you can check the board positions
for ex: if 1a and 2b and 3c are X (for the 1,2,3,a,b,c you can use arrays) you can check the arrays for the winner.

Share this post


Link to post
Share on other sites
Your approach should work, but there's a couple of flaws with it that I can see.

1. C++ Arrays are 0 based, not 1 based, i.e the first element of your board is board[0][0] not board[1][1]

2. There are 8 possible winning configurations in Tic Tac Toe. You're only checking 6 of them.

It might be worth breaking up that horrible if statement into a set of functions, e.g one to check for a vertical line, one to check for a horizontal line, and one to check for a diagonal line. These functions could also return a value representing the player that won.

Share this post


Link to post
Share on other sites
I tried that actually...what I had was this:


bool GameClass::IsWin()
{
if ((board[1][1] == board[1][2] && board[1][2] == board[1][3] && board[1][1]=='X' || 'O')||
(board[1][1] == board[2][1] && board[2][1] == board[3][1] && board[1][1]=='X' || 'O')||
(board[1][3] == board[2][3] && board[2][3] == board[3][3] && board[1][3]=='X' || 'O')||
(board[3][1] == board[3][2] && board[3][2] == board[3][3] && board[3][1]=='X' || 'O')||
(board[1][3] == board[2][2] && board[2][2] == board[3][1] && board[1][3]=='X' || 'O')||
(board[1][1] == board[2][2] && board[2][2] == board[3][3] && board[1][1]=='X' || 'O'))
{
{
GameClass::Winner(); return true;
}
else return false;
}



This works - i.e. the program runs, but it does not detect a winner. After every "X" or "O" is placed, I call GameClass::IsWin() in my gameloop to see if there is a winner. I'm honestly lost as to what the problem is...everything seems like I should be working properly yet it's not.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sandman
Your approach should work, but there's a couple of flaws with it that I can see.

1. C++ Arrays are 0 based, not 1 based, i.e the first element of your board is board[0][0] not board[1][1]

2. There are 8 possible winning configurations in Tic Tac Toe. You're only checking 6 of them.

It might be worth breaking up that horrible if statement into a set of functions, e.g one to check for a vertical line, one to check for a horizontal line, and one to check for a diagonal line. These functions could also return a value representing the player that won.


Thats exactly how i did it
CheckHorizontal, CheckVertical, and CheckCross all return true if there is a row.

Modular Coding is your friend :

Share this post


Link to post
Share on other sites

bool CheckVertical(char board[3][3], char letter)
{
for(int it = 0; it < 3; ++it)
{
if((board[it][0] == letter) && (board[it][1] == letter) && (board[it][2] == letter))
return true;
}
return false;
}

bool CheckHorizontal(char board[3][3], char letter)
{
for(int it = 0; it < 3; ++it)
{
if((board[0][it] == letter) && (board[1][it] == letter) && (board[2][it] == letter))
return true;
}
return false;
}

bool CheckCross(char board[3][3], char letter)
{
if(((board[0][0] == letter) && (board[1][1] == letter) && (board[2][2] == letter)) || ((board[2][0] == letter) && (board[1][1] == letter) && (board[0][2] == letter)))
return true;
return false;
}



Share this post


Link to post
Share on other sites
Quote:
Original post by SumDude
*** Source Snippet Removed ***


If you want to know which player won, you could modify these to return a char value 'O', 'X' or 0 instead of true/false, and have them check for any winner rather than call them once for each player.

Share this post


Link to post
Share on other sites
Success!

Thanks for the help you all...I cleaned up the code a little bit using for loops to check wins across the board and vertically, and two if statements to check the diagonals and ... it works!! I'm so excited...the hours finally paid off. :D

The fixed code:


int GameClass::IsWin()
{
// check wins across
for (int i_row = 1; i_row<4; i_row++)
{
if(board[i_row][1] == 'X' && board[i_row][2] == 'X' && board[i_row][3] == 'X')
{
winner = true;
return 1;
}
else if(board[i_row][1] == 'O' && board[i_row][2] == 'O' && board[i_row][3] == 'O')
{
winner = true;
return 2;
}

}
// check wins vertically
for (int j_col = 1; j_col<4; j_col++)
{
if(board[1][j_col] == 'X' && board[2][j_col] == 'X' && board[3][j_col] == 'X')
{
winner = true;
return 1;
}
else if(board[1][j_col] == 'O' && board[2][j_col] == 'O' && board[3][j_col] == 'O')
{
winner = true;
return 2;
}
}

// check diagonals
if(board[1][1] == 'X' && board[2][2] == 'X' && board[3][3] == 'X')
{
winner = true;
return 1;
}
else if(board[1][1] == 'O' && board[2][2] == 'O' && board[3][3] == 'O')
{
winner = true;
return 2;
}

if(board[1][3] == 'X' && board[2][2] == 'X' && board[3][1] == 'X')
{
winner = true;
return 1;
}
else if(board[1][3] == 'O' && board[2][2] == 'O' && board[3][1] == 'O')
{
winner = true;
return 2;
}

return 0;
}




Main game loop:

void GameLoop(void)
{
while (!game.IsWin() && game.turns < 10)
{
game.PrintBoard();
game.GetInput();
if(game.IsSpotTaken(game.row, game.col))
{ game.AlreadyTakenErr(); game.GetInput(); }
game.PlaceMark(game.row, game.col, game.id);
game.IsWin(); // returns 0 unless someone has won - in which case
} // returns 1 if player 1 (X) wins, 2 if player 2 (O) wins

if (game.turns < 10)
{
std::cout << "Congratulations to Player " << game.IsWin() << "! You are the winner!\n"; // prints value returned from GameClass::IsWin() - or the
} // player number

else
{
std::cout << std::endl;
std::cout << "Wow, you both played well. It ended up being a tie!\n";
}
}



Again, thanks a lot. You guys rock!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement