Thread: My first "real" C++ program! (Tic Tac Toe)

1. My first "real" C++ program! (Tic Tac Toe)

This is my very first game in C++. I am pretty proud of it even though it only took me about an hour and a half to do. My supposed AI isn't very good. I essentially generate a random number for the row and column and check to see if that position is open. If it is, then I make my move there. If not, then I generate another position and see if it's open. Not too bright, huh?.

Anyway, I was kind of looking for ways to improve this game. With respect to my AI, is there an easier way to figure out my moves other than brute force (ie, go through every scenario explicitly stating what my AI should do in each instance?) That would just get really tedious.

I am looking for any constructive criticisms you may have. Thanks in advance.

Oh, and if you happen to try to run this game and in the middle it seems to freeze, it's really not. It's probably the AI trying to figure out where to go.

Code:
```#include <iostream>
#include <cstdlib>
#include <time.h>

using namespace std;
int option, test, row, col, turn, option2 = 0;
char board[3][3];

//print the board to the screen
void drawBoard()
{
cout<<"\n";
for(int i = 0; i < 3; i++)
{
for(int j = 0; j < 3; j++)
{
cout<<"|"<<board[i][j]<<"|  ";
}
cout<<"\n-------------\n";
}
}

//this method returns a 0 if there's no winner, 1 if X wins, 2 if O wins, 3 if tie
int checkWinner()
{
//check to see if X won
if(board[0][0] == 'X' && board[0][1] == 'X' && board[0][2] == 'X')
return 1;
if(board[1][0] == 'X' && board[1][1] == 'X' && board[1][2] == 'X')
return 1;
if(board[2][0] == 'X' && board[2][1] == 'X' && board[2][2] == 'X')
return 1;

if(board[0][0] == 'X' && board[1][0] == 'X' && board[2][0] == 'X')
return 1;
if(board[0][1] == 'X' && board[1][1] == 'X' && board[2][1] == 'X')
return 1;
if(board[0][2] == 'X' && board[1][2] == 'X' && board[2][2] == 'X')
return 1;

if(board[0][0] == 'X' && board[1][1] == 'X' && board[2][2] == 'X')
return 1;
if(board[2][0] == 'X' && board[1][1] == 'X' && board[0][2] == 'X')
return 1;
//check to see if O won
if(board[0][0] == 'O' && board[0][1] == 'O' && board[0][2] == 'O')
return 0;
if(board[1][0] == 'O' && board[1][1] == 'O' && board[1][2] == 'O')
return 0;
if(board[2][0] == 'O' && board[2][1] == 'O' && board[2][2] == 'O')
return 0;

if(board[0][0] == 'O' && board[1][0] == 'O' && board[2][0] == 'O')
return 0;
if(board[0][1] == 'O' && board[1][1] == 'O' && board[2][1] == 'O')
return 0;
if(board[0][2] == 'O' && board[1][2] == 'O' && board[2][2] == 'O')
return 0;

if(board[0][0] == 'O' && board[1][1] == 'O' && board[2][2] == 'O')
return 0;
if(board[2][0] == 'O' && board[1][1] == 'O' && board[0][2] == 'O')
return 0;
}
//AI. generate a random move and see if it's available. if it is, then make it
//if it isn't then generate another random move
void AI()
{
col = -1;
row = -1;
while(col == -1 || row == -1)
{
time_t seconds;
time(&seconds);
srand((unsigned int) seconds);
col = rand()%3;
row = rand()%3;
if(board[row][col] != ' ')
{
col = -1;
row = -1;
}
board[row][col] = 'O';
}

}
int main()
{

do
{
option2 = 0; //so we can play multiple times
cout<<"-----------------------------\n\n";
cout<<"1. Play Tic Tac Toe\n";
cout<<"2. Quit\n";
cin>>option;
for(int i = 0; i < 3; i++)
{
for(int j = 0; j < 3; j++)
{
board[i][j] = ' ';
}
}
if(option !=2)
{
while(option2 != -1)
{
if(turn%2 == 0)//if it's even then it's X's turn
{
bool condition = true;
while(condition == true)
{
cout<<"\n\nEnter a move:\n";
cout<<"Enter the row you wish to make your move on (0,1,2)\n";
cin>>row;
cout<<"Enter the column you wish to make your move on (0,1,2)\n";
cin>>col;
if(board[row][col] == ' ')
{
board[row][col] = 'X';
turn++;
condition = false;
}
else
cout<<"Invalid move!\n";
}
}
else //AI must do something
{
AI();
turn++;
}

if(checkWinner() == 1) //X wins
{
cout<<"Congratulations! X won!\n\n";
option2 = -1;
}
else if(checkWinner() == 2) //X wins
{
cout<<"Congratulations! O won!\n\n";
option2 = -1;
}
drawBoard();
}

}

}while(option != 2);
cout<<"\n\n\n\nEnter anything to quit.";
cin>>test;
}```

2. I just did a search and there's a lot of info on the Tic Tac Toe AI. I guess any constructive criticism on my actually coding is really what I need then. Thanks in advance.

3. here are quite a few pointers--admitedly they're mostly issues that don't matter very much, like things that will save a few processor cycles, but they're good habits to get into in case you ever need teh skills.

just from the very top:
Code:
```#include <iostream>
#include <cstdlib>
#include <ctime>  //replacing <time.h>

using namespace std;
int option, test, row, col, turn, option2 = 0;  //try not to use global variables if you don't have to
char board[3][3];```
from the very bottom:
Code:
```      cout<<"\n\n\n\nEnter anything to quit.";
cin>>test;```
this would probably serve you better:
Code:
```  cout<<"\n\n\n\nPress ENTER to quit";
cin.get();```
I'm not sure if you already covered this one somewhere else in your code:
Code:
```        if(board[row][col] != ' ')  //does this mean it can take a spot X already has?
{
col = -1;
row = -1;
}
board[row][col] = 'O';```
I don't think you have the 'tie' case done yet - I finished a game with no winner an it was stuck asking me for my move:
Code:
```//this method returns a 0 if there's no winner, 1 if X wins, 2 if O wins, 3 if tie
int checkWinner()
{
//check to see if X won
...
//check to see if O won
...
}```
and here is a similar issue (I also found an error in one of your comments):
Code:
```      //try not to call checkWinner() two times - use a variable like this:
winner=checkWinner();
if(winner==1) //X wins
{
cout<<"Congratulations! X won!\n\n";
option2 = -1;
}
else if(winner==2) //O wins <-- an error in your comment
{
cout<<"Congratulations! O won!\n\n";
option2 = -1;
}
else if(winner==3)  //nobody wins
{
cout<<"It's a Draw\n\n";
option2 = -1;
}
drawBoard();```
here's something involving your randomness code:
Code:
```  /*

time_t seconds;
time(&seconds);
srand((unsigned int) seconds);

you can use this method, which eliminates the need for a variable:
*/

srand((unsigned int)time(0));```

4. With respect to my AI, is there an easier way to figure out my moves other than brute force (ie, go through every scenario explicitly stating what my AI should do in each instance?) That would just get really tedious.
For something as small as tic-tac-toe, pre-calculation probably is the best, especially since there are only a few variations, the rest just need the board to be rotated.

On the other hand, a simple rule of thumb would be "if opponent starts in the centre, reply in the corner; else reply in the centre".
This wouldnt help your program recognise wins, but it'll help your program avoid losing, unless the player makes a quiet 2nd move, forcing the random choice, which may be the choice of a lost variation.

5. Thank you for the help guys. I really appreciate the suggestions.

6. good luck on further projects : if you make a version 2 , show us !

7. > time_t seconds;
> time(&seconds);
> srand((unsigned int) seconds);
This should be in main(). Otherwise you're seeding the random number generator every time you make a move.