// Return Value: integer that is either a 0,1,2, or -1.
You should indicate what these values mean. It looks like 1 means X won, 2 means O won, 0 means it's a draw and -1 means nobody has won. The rest of my post will assume this is right.
The consistent problem I see in your code is that you're not taking advantage of variables. For example, the problem in getGameState() is that somewhere in that mass of if/then/else, there's a bug. It only takes one misplaced number to screw it up. You can simplify this stuff by using loops instead:
1 2 3 4 5 6 7 8
|
// Check if X won on a row:
for (int start = 1; start <= 9; start += 3) {
if (ticTac[start] == ticTac[start+1] &&
ticTac[start] == ticTac[start+2] &&
ticTac[start] == 'X') {
return 1;
}
}
|
The first time through the loop start is 1 so it compares squares 1,2 and 3.
The second time through start is 4 and it compares 4,5,6. Then it compares 7 8 9.
Similar code can check for a column:
1 2 3 4 5 6 7 8
|
// Check if X won on a column:
for (int start = 1; start <= 3; ++start) {
if (ticTac[start] == ticTac[start+3] &&
ticTac[start] == ticTac[start+6] &&
ticTac[start] == 'X') {
return 1;
}
}
|
You'll have to check the diagonals the hard way:
1 2 3
|
if (ticTac[1] == ticTac[5] && ticTac[1] == ticTac[9] && ticTac[1] == 'X')
return 'X';
// and similar code for the other diagonal.
|
You can also use a loop to see if it's a draw. After you've determined that nobody has won:
1 2 3 4
|
for (int i=1; i<10; ++i) {
if (ticTac[i] != i) return -1; // board not full
}
return 1; // board is full
|
See how this works? Rather than explicityly checking ticTac[1], ticTac[2] etc., I use different values of i to check each square.
In your main program, you have variables x and o, but really what you want is the a variable that records the state of the board. Just call it
state
. This will make some bugs in the main loop more obvious. In your main loop you want to do this:
1 2 3 4 5 6 7 8 9 10
|
playerXTurn();
if (getGameState() == 1) {
// say X won
break;
}
playerOTurn()
if (getGameState() == 2) {
// say O won
break;
}
|
On the same theme of not using variables effectively, look at playerXTurn(). You can get rid of almost all the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
void playerXTurn()
{
int square;
char mark = 'X';
displayGameBoard();
cout << " Enter a location for 'X' or enter <T> to terminate the game: " << endl
<< " Please enter your selection > ";
cin >> square;
if (square <1 || square > 9)
{
cout << " Selection is out of range, select a location between 1 and 9 " << endl;
} else if (ticTac[square] != square)
{
cout << "This space is already occuppied, select another space." << endl;
} else {
ticTac[square] = mark;
}
|
Do the same thing with playerOMove. When you're done, notice that playerXMove() and playerOMove() are nearly identical. They should differ by just one line of code. Can you create a single function called playerMove() that can replace them both? Hint: pass a parameter to playerMove() and call it with different values of the parameter.
I hope this helps.