2

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.

123
  • 8,733
  • 14
  • 57
  • 99
  • 2
    Using `std::vector>` for a tictactoe board is overkill and comes with _huge_ drawbacks. You should define a `TicTacToeBoard` class with nine values representing the state (empty, x or o) of the nine squares (NW, N, NE, W, C, E, SW, S, SE) of a game. – YSC Mar 08 '16 at 17:04
  • 1
    BTW, if you represent your board as a 3x3 {-1,0,1} matrix A, `[ 1 1 1 ]*A` and `A*[1 1 1]^T` tells you if there's a winner and who wins: if any of the compound of the multiplication results is 3, 1 wins, if it is -3, 1- wins. – YSC Mar 08 '16 at 17:12

3 Answers3

2

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

wonton
  • 7,568
  • 9
  • 56
  • 93
0

You're complicating things a little bit.
You don't need to first collect which positions a player has used and see how many of those are in a winning position.
Since you already know the winning positions, you only need to check if any one player has occupied all of one.

Assuming that ' ' marks an empty square,

for(const auto& win: possibleWins)
{
    if (board[win[0]] == board[win[1]] 
     && board[win[1]] == board[win[2]]
     && board[win[0]] != ' ')
    {
        // if board[win[0]] == 'X' , then X won
        // if board[win[0]] == 'O' , then O won
    }
}

should do.

molbdnilo
  • 64,751
  • 3
  • 43
  • 82
0
   |   |
---+---+---
   |   |   
---+---+---
   |   |   

is a int myArray[9]; and you put the player moves on it myArray[played_position] = playerValue;, then you could use your 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}}; to check after the 3 move if the positions correspond to the same value (player!)...

for(int idx=0; idx<possibleWins.size(); idx++)
{
   if(myArray[possibleWins[idx][0]] == myArray[possibleWins[idx][1]] == myArray[possibleWins[idx][2]])
      {
          return myArray[possibleWins[idx][0];
      }
 }

It's just an idea, hope it helps you elaborate....

DIEGO CARRASCAL
  • 1,999
  • 14
  • 16