Alex Montague
Alex Montague

Reputation: 88

Java - Determining a tie in tic tac toe?

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 ;
                }
            }  
        }
     }   

Upvotes: 1

Views: 7997

Answers (7)

Jesus Garcia
Jesus Garcia

Reputation: 1

Im kind of late to the party here but why not just make a variable that keeps track of the number of moves? Set it to 0 at the beginning and every time a move is made (whether an X or O is placed), increment it by 1. Then once it gets to 9 you can display your tie message. This is a lot simpler than checking every single slot.

Upvotes: 0

Edouard Gotthardt
Edouard Gotthardt

Reputation: 11

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;
}

Upvotes: 1

Oblivion
Oblivion

Reputation: 1

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;
}

Upvotes: 0

akhil_mittal
akhil_mittal

Reputation: 24157

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;
    }`

Upvotes: 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

Upvotes: 0

ajb
ajb

Reputation: 31689

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

Upvotes: 1

frasnian
frasnian

Reputation: 2003

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 ;    
    }
}

Upvotes: 0

Related Questions