I'm creating a tictactoe game, and every move I need to test whether a player has won or not, and it's giving me a lot of trouble. I have a 2d vector of all the possible win combinations:
vector<vector<int>> possibleWins {{1,2,3},{4,5,6},{7,8,9},{1,4,7},{2,5,8},{3,6,9},{1,5,9},{3,5,7}};
Every move I loop through the 2d vector and append player1 and player2 vectors with any cells they have marked:
vector<int> totalX {};
vector<int> totalO {};
int count = 1;
for(int i=0; i<3; i++) {
for(int j=0; j<3; j++) {
if(board[i][j] == 'x') {
if(totalX.size() == 0) {
totalX.push_back(count);
}
for(int k=0; k<totalX.size(); k++) {
if(count == totalX[k]) {
break;
}
else {
totalX.push_back(count);
}
}
}
else if(board[i][j] == 'o') {
if(totalO.size() == 0) {
totalO.push_back(count);
}
for(int k=0; k<totalO.size(); k++) {
if(count == totalO[k]) {
break;
}
else {
totalO.push_back(count);
}
}
}
count++;
}
}
I then try to test whether the cells in each players cell vector is a winning combination of cells, and this is proving to be difficult for me:
int xInRow = 0;
for(int x=0; x<totalX.size(); x++) {
for(int y=0; y<possibleWins.size(); y++) {
xInRow = 0;
for(int z=0; z<3; z++) {
if(totalX[x] == possibleWins[y][z]) {
xInRow++;
if(xInRow == 3) {
return X_WON;
}
}
}
}
}
This does not work, and I've tried implementing it in numerous different ways, but I honestly have no idea how to enumerate through all the possible wins and test if a player has one of these combinations.
Is there a way I could structure this better to make it work? I'm pretty lost on this.
There are two approaches. Your code is a bit too complicated for what should be a simple operation so I'm not going to try to understand it.
I agree with YSC that you don't need a std::vector. You know it's a 3x3 grid every time, so a 3x3 enum array should be much better. Something like
enum TTTState {
EMPTY=0,
X,
O
}
TTState board[3][3];
would save you a lot of headache. You can say board[0][0]
is the top left, and board[2][2]
is the bottom right.
Option 1
I like your idea of possibleWins, so with the new board[3][3]
data structure, you can store pair of numbers with int solutions[8][3][2]
but this is already kind of messy.
for each solution in solutions
for each triplet in solution
for each pair in triplet
if board[pair[0]][pair[1]] matches all other pair in triplet
then whoever has pieces in the row has won
Option 2
This is probably cleaner. There are 3 possible ways to win. Horizontal, vertical, and diagonal. You can check these three ways separately.
for i = 0 ; i != 3; i++
type = board[i][0]
won = true
for ii = 1; ii != 3; ii++
if board[i][ii] is not type
won = false
if won then you can return the function with who won
for i = 0 ; i != 3; i++
type = board[0][i]
won = true
for ii = 1; ii != 3; ii++
if board[ii][i] is not type
won = false
if won then you can return the function with who won
Diagonal can just be hard coded, since there are only two possible victory positions..