// 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.