1

I have my code working great, just need to know how to determine a tie. It is difficult because I am working with chars to fill the spaces on my tic tac toe board, and am not sure of a way to check if every square has either an 'X' or an 'O' and if all the squares do, make it a tie.

This is my code so far:

Thanks!

/** Board[][] char filled array with either 'X', 'O' or '-'. 
returns true if the game is a tie, false if its not */

     public static void Tie (char [] [] Board)        //Tie Method
     {
             for (int row = 0; row < 3; row = row + 1) 
        {
            for (int column = 0; column < 3; column = column + 1) 
            {
                if (Board [row] [column] == 'X' && Board [row] [column] == 'O') 
                {
                    System.out.println ("It is a tie. Cats game!") ;
                    GameOver = true ;
                }
            }  
        }
     }   
Mike G
  • 4,232
  • 9
  • 40
  • 66
Alex Montague
  • 78
  • 3
  • 14
  • You might try removing all the code except for the `Tie` method and add a comment at the top saying something like `/** Board[][] char filled array with either 'X', 'O' or '-'. returns true if the game is a tie, false if its not */` – ug_ Jan 07 '15 at 04:06
  • Uhh, that's just commenting and will not really help me that much, but thanks! – Alex Montague Jan 07 '15 at 04:08
  • 1
    yes, that is why its a comment and not an answer. It would help others who would like to awnser your question to see the problem more easily therefore you will be much more likely to get help. – ug_ Jan 07 '15 at 04:11
  • 1
    OP: @ug_'s comment is actually quite helpful, it you listen to what he/she is saying. Your only question appears to be this: "just need to know how to determine a tie". So, if all of your (other) "code [is] working great," the real question you have is much more limited in scope. More people would be willing to help with your current *specific* issue if they don't have to wade through a bunch of essentially extraneous/irrelevant code. Asking better questions leads to better answers. In this particular case a more specific question is probably better. – frasnian Jan 07 '15 at 04:20
  • each character has an unique integer equivalent. So every time a player wins, the row or column contains X X X or O O O. if you add these, a unique number is obtained. So you can check if all the boxes are filled and if non of the row and column give that unique value(X+X+X or O+O+O) then you know that the game is tied. – hermit Jan 07 '15 at 04:24
  • This test: `Board [row] [column] == 'X' && Board [row] [column] == 'O'` makes no sense, because it can never be true. You're testing whether the same square on the board is both `X` and `O`, and of course it can't be both. – ajb Jan 07 '15 at 04:42
  • @ajb absolutely agree with you. Even I was confused what is happening. – akhil_mittal Jan 07 '15 at 04:45
  • This also looks similar `http://stackoverflow.com/questions/4198955/how-to-find-the-winner-of-a-tic-tac-toe-game-of-any-size` – akhil_mittal Jan 07 '15 at 04:47

6 Answers6

1

To do the best at avoiding duplicated code, I'd define a method like this:

boolean checkLine(char[][] board, int startRow, int startCol, int rowDiff, int colDiff) {
    ...
}

which checks to see if board[startRow][startCol], board[startRow+rowDiff][startCol+colDiff], and board[startRow+2*rowDiff][startCol+2*colDiff] are all the same (and are either X or O). You should be able to see that all 8 lines (3 rows, 3 columns, 2 diagonals) can be tested using the right values for the parameters (possibly negative). Then call this method up to 8 times; if any of them return true, the game is a win for one player; if none of them return true, and there are no empty spaces on the board, the game is a tie. (An improvement might be to make the result type char instead of boolean, and have the method return X or O if the three cells are all the same, or something else if they're not. That way, the method would tell you who won if a player won.)

ajb
  • 31,309
  • 3
  • 58
  • 84
1

This is how I went about checking for a tie for the project that I just had to do. Keep in mind I'm a first year CS student, yet all of my tests seemed to work rather well.

 public boolean checkTie() {
    int blanks = 0;
    int xChance = 0,
        xCount = 0;
    int oChance = 0,    // How many points on the board O could win (Same above for X's) 
        oCount = 0;     // Number of O's in a row or column given the loop iteration (")
    int blankCount = 0;

    // Counts how many blank spaces are left on the game board
    // This takes place of keeping track of who is playing since
    // X is hardcoded to always go first and therefor will always
    // have 5 moves while O will only ever have 4. We use this information
    // to tell us who is playing based on the number of blank spaces left
    // i.e. if only 1 blank left then it's X's turn & 2 = O's turn.
    for (int i = 0; i < 3; i ++) {
        for (char[] row : board) {
            if (row[i] == ' ') {
                blanks++;
            }
        }
    }

    if (blanks <= 3) {

        // Check's downward slope diagonal if there is a blank, X, or O
        // in each respective space. If so then the count is incremented
        // by how many for each matching variable. If the count meets the 
        // right condition then the player is given a chance to win.
        for (int i = 0; i < 3; i++) {
            if (board[i][i] == 'X') {
                xCount++;
            }
            if (board[i][i] == 'O') {
                oCount++;
            }
            if (board[i][i] == ' ') {
                blankCount++;
            }
            if ((xCount == 2) && (blankCount == 1) && (blanks >= 1)) {
                xChance++; // COULD WIN
            }
            if ((oCount == 2) && (blankCount == 1) && (blanks >= 2)) {
                oChance++; // COULD WIN
            }
            // Resets the count so that the next row has a fresh count.
            if (i >= 2) {
                xCount = 0;
                oCount = 0;
                blankCount = 0;
            }
        }

        // Checks the upward slope diagonal if there is a blank, X, or O
        // in each respective space. I wasn't too sure how to loop through this 
        // So i just manually/hard coded the checks.
        // As with all other row/col/upslope checks at the end I reset the count
        // to get ready for the next loop check.
        if (board[0][2] == 'X') {
            xCount++;
        }
        if (board[0][2] == 'O') {
            oCount++;
        }
        if (board[0][2] == ' ') {
            blankCount++;
        }
        if (board[1][1] == 'X') {
            xCount++;
        }
        if (board[1][1] == 'O') {
            oCount++;
        }
        if (board[1][1] == ' ') {
            blankCount++;
        }
        if (board[2][0] == 'X') {
            xCount++;
        }
        if (board[2][0] == 'O') {
            oCount++;
        }
        if (board[2][0] == ' ') {
            blankCount++;
        }
        if ((xCount == 2) && (blankCount == 1) && (blanks >= 1)) {
            xChance++; // COULD WIN
        }
        if ((oCount == 2) && (blankCount == 1) && (blanks >= 2)) {
            oChance++; // COULD WIN
        }
        xCount = 0;
        oCount = 0;
        blankCount = 0;


        // Check the rows to see what is in each space
        // If X increment that row's count of X's and same if O
        // After each incrementing the values are compared to see
        // if X or O has 2 spots held alongside a blank space,
        // if so then the player is given a "chance to win" meaning that the game
        // will go on if the number of blanks(turns left) allows
        // for that player to go again.
        // The loop ends by reseting the counts of X's and O's so 
        // that the next row count will be 'fresh'
        for (char[] row : board) {
            for (int i = 0; i < 3; i++) {
                if (row[i] == 'X') {
                    xCount++;
                }
                if (row[i] == 'O') {
                    oCount ++;
                }
                if (row[i] == ' ') {
                    blankCount++;
                }
                if ((xCount == 2) && (blankCount == 1) && (blanks >= 1)) {
                    xChance++; // COULD WIN
                }
                if ((oCount == 2) && (blankCount == 1) && (blanks >= 2)) {
                    oChance++; // COULD WIN
                }
                // Resets the count so that the next row has a fresh count.
                if (i >= 2) {
                    xCount = 0;
                    oCount = 0;
                    blankCount = 0;
                }
            }
        }

        // Does that same thing as the loop that checks for the 
        // rows yet does this for the columns where i is the fixed position
        // for the column (only changing to the next column once check from 
        // top to bottom by the inner for loop) 
        for (int i = 0; i < 3; i ++) {

            for (int space = 0; space < 3; space++) {
                if (board[space][i] == 'X') {
                    xCount++;
                }
                if (board[space][i] == 'O') {
                    oCount++;
                }
                if (board[space][i] == ' ') {
                    blankCount++;
                }
                if(xCount == 2 && blankCount == 1) {
                    xChance++;
                }
                if (oCount == 2 && blankCount == 1) {
                    oChance++;
                }
                // Resets the count so that the next column has a fresh count.
                if (space >= 2) {
                xCount = 0;
                oCount = 0;
                blankCount = 0;
                }
            }
        }

        // If it's the last turn and X has no chance to win then 
        // returns true which will equal a tie.
        if (blanks <= 1 && xChance == 0) {
            return true;
        }

        // If either player has a chance to win then the number of chances
        // will reset to 0 for the next time the method is called
        // and then false will be returned telling the game to continue.
        if ((oChance > 0 && blanks >= 2) || (xChance > 0 && blanks >= 1)) {
            xChance = 0;
            oChance = 0;
            return false;
        }
        else {
            return true;
        }
    }
    return false;
}
0

Check for a win before checking for a tie. Then, all you really need is a simple "BoardFull" method - by definition a full board without a win is a draw. Assume that you have a sentinel character (let's say '.') to mark spaces that have not had an 'X' or 'O' move yet:

public static bool BoardFull(char [] [] Board)
{
    for (int row = 0; row < 3; ++row) 
    {
        for (int column = 0; column < 3; ++column) 
        {
            if (Board [row] [column] == '.')
            {
                // a move still exists - board is not full
                return false;
            }
        }  
    }
    return true;
 }

Then, it's basically (pseudo-code follows):

if (!HaveWin(board))
{
    if (BoardFull(board))
    {
        System.out.println ("It is a tie. Cats game!") ;
        GameOver = true ;    
    }
}
frasnian
  • 1,973
  • 1
  • 14
  • 24
0

Check all the possible rows/columns/diagonals a player can score and keep track of the X and O score. Then compare the two to determine a tie.

public static void Tie (char [] [] Board)
{
    //do a check to make sure the Board is 3x3
    //if not, return/throw an error

    //keep track of score
    int xScore = 0;
    int oScore = 0;

    //horizontal and vertical checks
    for(int i = 0; i < Board.length; i++){
        if(Board[i][0] == 'X' &&   Board[i][1] == 'X' && Board[i][2] == 'X'){
            xScore++;
        }

        if(Board[0][i] == 'X' &&   Board[1][i] == 'X' && Board[2][i] == 'X'){
            xScore++;
        }

        if(Board[i][0] == 'O' &&   Board[i][1] == 'O' && Board[i][2] == 'O'){
            oScore++;
        }

        if(Board[0][i] == 'O' &&   Board[1][i] == 'O' && Board[2][i] == 'O'){
            oScore++;
        }
    }

    //diagonal checks
    if(Board[0][0] == 'X' &&   Board[1][1] == 'X' && Board[2][2] == 'X'){
        xScore++;
    }
    if(Board[0][2] == 'X' &&   Board[1][1] == 'X' && Board[2][0] == 'X'){
        xScore++;
    }
    if(Board[0][0] == 'O' &&   Board[1][1] == 'O' && Board[2][2] == 'O'){
        oScore++;
    }
    if(Board[0][2] == 'O' &&   Board[1][1] == 'O' && Board[2][0] == 'O'){
        oScore++;
    }

    if(xScore == 0 && oScore == 0){
        System.out.println ("It is a tie. Cats game!") ;
        GameOver = true ;
    }else{
        //do other stuff
    }
}

NOTE: I haven't actually tested this pseudo code out, but you should get the idea

  • I don't know about `xScore == oScore`. If they're both 0, it's a tie. If they're both equal and are not 0, something must have really gotten screwed up earlier, because it means that one player won but the program made them keep playing. – ajb Jan 07 '15 at 04:44
  • @ajb Good catch. It should be `xScore == 0 && oScore == 0` – But I'm Not A Wrapper Class Jan 07 '15 at 04:46
0

The following link may help. This algorithm is about tic-tac-toe game played between computer and human. And for tie it makes use of similar algorithm as suggested by @frasnian.

http://www.cs.colostate.edu/~cs160/.Fall14/examples/TicTacToe.html

` // Game status
    private eStatus status() {

        // Check tie
        boolean tieGame = true;
        for (int row = 0; row <= 2; ++row)
            for (int col = 0; col <= 2; ++col)
                    if (board[row][col] == '-')
                        tieGame = false;
        // Tie game
        if (tieGame)
            return eStatus.TIE_GAME;

        // Player wins
        else if (runOfThree('O'))
            return eStatus.PLAYER_WINS;

        // Computer wins
        else if (runOfThree('X'))
            return eStatus.COMPUTER_WINS;

        return eStatus.IN_PROGRESS;
    }`
akhil_mittal
  • 23,309
  • 7
  • 96
  • 95
0

I have finally found the solution! :O Here it is, for both win/tie. Do note though that this is just coming from an amateur coder. Hope it helps though. :)

static int winOrTie() {
    //TODO Determine whether X or O won or there is a tie
    if (gameboard[0][0] + gameboard[0][1] + gameboard[0][2] == 3*NOUGHT)
        {return NOUGHT;}
    if (gameboard[1][0] + gameboard[1][1] + gameboard[1][2] == 3*NOUGHT)
        {return NOUGHT;}
    if (gameboard[2][0] + gameboard[2][1] + gameboard[2][2] == 3*NOUGHT)
        {return NOUGHT;}
    
    if (gameboard[0][0] + gameboard[1][0] + gameboard[2][0] == 3*NOUGHT)
        {return NOUGHT;}
    if (gameboard[0][1] + gameboard[1][1] + gameboard[2][1] == 3*NOUGHT)
        {return NOUGHT;}
    if (gameboard[0][2] + gameboard[1][2] + gameboard[2][2] == 3*NOUGHT)
        {return NOUGHT;}
    if (gameboard[0][0] + gameboard[1][1] + gameboard[2][2] == 3*NOUGHT)
        {return NOUGHT;}
    if (gameboard[0][2] + gameboard[1][1] + gameboard[2][0] == 3*NOUGHT)
        {return NOUGHT;}
    
    if (gameboard[0][0] + gameboard[0][1] + gameboard[0][2] == 3*CROSS)
        {return CROSS;}
    if (gameboard[1][0] + gameboard[1][1] + gameboard[1][2] == 3*CROSS)
        {return CROSS;}
    if (gameboard[2][0] + gameboard[2][1] + gameboard[2][2] == 3*CROSS)
        {return CROSS;}
    
    if (gameboard[0][0] + gameboard[1][0] + gameboard[2][0] == 3*CROSS)
        {return CROSS;}
    if (gameboard[0][1] + gameboard[1][1] + gameboard[2][1] == 3*CROSS)
        {return CROSS;}
    if (gameboard[0][2] + gameboard[1][2] + gameboard[2][2] == 3*CROSS)
        {return CROSS;}
    if (gameboard[0][0] + gameboard[1][1] + gameboard[2][2] == 3*CROSS)
        {return CROSS;}
    if (gameboard[0][2] + gameboard[1][1] + gameboard[2][0] == 3*CROSS)
        {return CROSS;}
    
    if (gameboard[2][2] + gameboard[1][2] + gameboard[1][1] + gameboard[0][1] + gameboard[2][0] == 5*NOUGHT)
        {return 0;}
    if (gameboard[0][0] + gameboard[1][0] + gameboard[1][1] + gameboard[2][1] +  gameboard[0][2] == 5*NOUGHT)
        {return 0;}
    if (gameboard[0][2] + gameboard[1][2] + gameboard[1][1] + gameboard[2][1] + gameboard[0][0] == 5*NOUGHT)
        {return 0;}
    if (gameboard[2][0] + gameboard[2][1] + gameboard[1][1] + gameboard[1][2] + gameboard[0][0] == 5*NOUGHT)
        {return 0;}
    if (gameboard[0][0] + gameboard[0][1] + gameboard[1][1] + gameboard[1][2] + gameboard[2][0] == 5*NOUGHT)
        {return 0;}
    if (gameboard[2][0] + gameboard[1][0] + gameboard[1][1] + gameboard[0][1] + gameboard[2][2] == 5*NOUGHT)
        {return 0;}
    if (gameboard[0][2] + gameboard[0][1] + gameboard[1][1] + gameboard[1][0] + gameboard[2][2] == 5*NOUGHT)
        {return 0;}
    if (gameboard[2][2] + gameboard[2][1] + gameboard[1][1] + gameboard[1][0] + gameboard[0][2] == 5*NOUGHT)
        {return 0;}
    if(gameboard[0][2] + gameboard[0][1] + gameboard[1][2] + gameboard[2][1] +  gameboard[1][0] == 5*NOUGHT)
        {return 0;}
    if(gameboard[0][0] + gameboard[1][0] + gameboard[0][1] + gameboard[2][1] +  gameboard[1][2] == 5*NOUGHT)
        {return 0;}
    if(gameboard[2][0] + gameboard[1][0] + gameboard[2][1] + gameboard[0][1] +  gameboard[1][2] == 5*NOUGHT)
        {return 0;}
    if(gameboard[2][2] + gameboard[1][2] + gameboard[2][1] + gameboard[0][1] +  gameboard[1][0] == 5*NOUGHT)
        {return 0;}
    if (gameboard[0][2] + gameboard[0][1] + gameboard[1][2] + gameboard[1][0] + gameboard[2][0] == 5*NOUGHT)
        {return 0;}
    if (gameboard[0][2] + gameboard[0][1] + gameboard[2][1] + gameboard[2][0] + gameboard[2][1] == 5*NOUGHT)
        {return 0;}
    if (gameboard[0][0] + gameboard[0][1] + gameboard[1][0] + gameboard[2][1] + gameboard[2][2] == 5*NOUGHT)
        {return 0;}
    if (gameboard[0][0] + gameboard[0][1] + gameboard[1][0] + gameboard[1][2] + gameboard[2][2] == 5*NOUGHT)
        {return 0;}
    if (gameboard[2][2] + gameboard[2][1] + gameboard[1][2] + gameboard[1][0] + gameboard[0][0] == 5*NOUGHT)
        {return 0;}
    if (gameboard[2][2] + gameboard[2][1] + gameboard[1][2] + gameboard[0][1] + gameboard[0][0] == 5*NOUGHT)
        {return 0;}
    if (gameboard[2][0] + gameboard[2][1] + gameboard[1][0] + gameboard[0][1] + gameboard[0][2] == 5*NOUGHT)
        {return 0;}
    if (gameboard[2][0] + gameboard[2][1] + gameboard[1][0] + gameboard[1][2] + gameboard[2][2] == 5*NOUGHT)
        {return 0;}
    if (gameboard[2][0] + gameboard[1][0] + gameboard[2][1] + gameboard[0][2] + gameboard[0][1] == 5*NOUGHT)
        {return 0;}
    if (gameboard[2][0] + gameboard[1][0] + gameboard[2][1] + gameboard[1][2] + gameboard[0][2] == 5*NOUGHT)
        {return 0;}
    if (gameboard[0][0] + gameboard[0][2] + gameboard[1][2] + gameboard[2][0] + gameboard[2][1] == 5*NOUGHT)
        {return 0;}
    if (gameboard[2][2] + gameboard[0][1] + gameboard[0][2] + gameboard[1][0] + gameboard[2][0] == 5*NOUGHT)
        {return 0;}
    if (gameboard[0][2] + gameboard[1][0] + gameboard[0][0] + gameboard[2][2] + gameboard[2][1] == 5*NOUGHT)
        {return 0;}
    if (gameboard[2][0] + gameboard[2][2] + gameboard[1][2] + gameboard[0][0] + gameboard[0][1] == 5*NOUGHT)
        {return 0;}
    if (gameboard[0][0] + gameboard[0][1] + gameboard[2][0] + gameboard[2][1] + gameboard[1][2] == 5*NOUGHT)
        {return 0;}
    if (gameboard[2][0] + gameboard[1][0] + gameboard[2][2] + gameboard[1][2] + gameboard[0][1] == 5*NOUGHT)
        {return 0;}
    if (gameboard[0][1] + gameboard[0][2] + gameboard[2][1] + gameboard[2][2] + gameboard[1][0] == 5*NOUGHT)
        {return 0;}
    if (gameboard[0][0] + gameboard[1][0] + gameboard[0][2] + gameboard[1][2] + gameboard[2][1] == 5*NOUGHT)
        {return 0;}


    return -2;
}