
public class TicTacToeBoard {
    char[][] board;
    
    /**
     * Constructs a new tic-tac-toe board, with
     * all spaces blank.
     */
    TicTacToeBoard() {
        board = new char[][] {{' ', ' ', ' '},
                              {' ', ' ', ' '},
                              {' ', ' ', ' '}};
    }

    /**
     * Puts the designated character into the specified row
     * and column of this tic-tac-toe board, where the rows and
     * columns are numbered from 1 to 3. Some error checking
     * is done.
     * 
     * @param row The row number (1..3).
     * @param column The column number (1..3).
     * @param ch The character ('X' or 'O') to put there.
     */
    void set(int row, int column, char ch) {
        if (board[row - 1][column - 1] != ' ') {
            error("Row " + row + ", column " + column +
            " is already taken.");
        }
        else if (ch != 'X' && ch != 'O') {
            error("Illegal character: " + ch);
        }
        else {
            board[row - 1][column - 1] = ch;
        }
    }
    
    /**
     * Returns the character ('X', 'O', or space) in the
     * specified row and column of this tic-tac-toe board.
     * 
     * @param row The row number (1..3).
     * @param column The column number (1..3).
     * @return The character ('X', 'O', or space) in that location.
     */
    char get(int row, int column) {
        return board[row - 1][column - 1];
    }
    
    /**
     * Returns true if the indicated row and column in this
     * tic-tac-toe board is available.
     * 
     * @param row The row number (1..3).
     * @param column The column number (1..3).
     * @return <code>true</code> if the location is available.
     */
    boolean isEmpty(int row, int column) {
        return board[row - 1][column - 1] == ' ';
    }
    
    /**
     * Prints this tic-tac-toe board.
     */
    void print() {
        printThree(board[0][0], board[0][1], board[0][2]);
        printLine();
        printThree(board[1][0], board[1][1], board[1][2]);
        printLine();
        printThree(board[2][0], board[2][1], board[2][2]);
        System.out.println();
    }

    /**
     * Prints three characters ('X', 'O', or space), with
     * separators, in one row of this tic-tac-toe board.
     * 
     * @param ch1 The leftmost character in this row.
     * @param ch2 The middle character in this row.
     * @param ch3 The rightmost character in this row.
     */
    private void printThree(char ch1, char ch2, char ch3) {
        System.out.println(" " + ch1 + " | " + ch2 + " | " + ch3);
    }
    
    /**
     * Prints a horizontal line for this tic-tac-toe board.
     */
    private void printLine() {
        System.out.println("---|---|---");
    }

    /**
     * Prints the given error message.
     * 
     * @param errorMessage The message to print.
     */
    private void error(String errorMessage) {
        System.out.println(errorMessage);
    }
    
// The following main method is just for testing; discard
    
    public static void main(String[] args) {
        TicTacToeBoard b = new TicTacToeBoard();
        b.set(1, 1, 'X');
        b.set(2, 2, 'O');
        b.set(3, 3, 'X');
        b.print();
    }

// The following methods are to be written by students
    
    boolean gameIsOver() {
        if (computerHasWon()) return true;
        if (humanHasWon()) return true;
        for (int row = 1; row <= 3; row++) {
            for (int column = 1; column <= 3; column++) {
                if (isEmpty(row, column)) return false;
            }
        }
        return true;
    }

    boolean computerHasWon() {
        return playerWithThisCharacterHasWon('X');
    }

    boolean humanHasWon() {
        return playerWithThisCharacterHasWon('O');
    }
    
    private boolean playerWithThisCharacterHasWon(char ch) {
        if (get(1, 1) == ch && get(1, 2) == ch && get(1, 3) == ch) return true;
        if (get(2, 1) == ch && get(2, 2) == ch && get(2, 3) == ch) return true;
        if (get(3, 1) == ch && get(3, 2) == ch && get(3, 3) == ch) return true;
        
        if (get(1, 1) == ch && get(2, 1) == ch && get(3, 1) == ch) return true;
        if (get(1, 2) == ch && get(2, 2) == ch && get(3, 2) == ch) return true;
        if (get(1, 3) == ch && get(2, 3) == ch && get(3, 3) == ch) return true;
        
        if (get(1, 1) == ch && get(2, 2) == ch && get(3, 3) == ch) return true;
        if (get(1, 3) == ch && get(2, 2) == ch && get(3, 1) == ch) return true;
        return false;
    }
}