public class TicTacToe {
  
  // This is a constant.
  // Constant names are all uppercase.
  // Constants cannot be reassigned once
  // they have been initialized.
  public static final int BOARD_SIZE = 3;
 
  /** An empty square on the board. */
  private static final char BLANK_SQUARE = ' ';
  
  
  /** The tic-tac-toe board. */
  private char[][] board;
  
  
  /** 
   * Create a new tic tac toe board. 
   */
  public TicTacToe() {
   board = new char[BOARD_SIZE][BOARD_SIZE];
   
   // for each row on the board
   for(int r = 0; r < BOARD_SIZE; r++ ) {
     
     // for each column
     for(int c= 0; c < BOARD_SIZE; c++) {
       board[r][c] = BLANK_SQUARE;
     }
   }
  }
  
  /**
   * Set a mark on the board.
   */
  public void setMark(int row, int col, char mark) {
    board[row][col] = mark;
  }
  
  /**
   * Get the mark from the board.
   */
  public char getMark(int row, int col) {
    return board[row][col];
  }
  
  /** 
   * Displaying the board.
   */
  public String toString() {
    String result = "";
    
    // for each row on the board
   for(int r = 0; r < BOARD_SIZE; r++ ) {
     
     // for each column
     for(int c= 0; c < BOARD_SIZE; c++) {
       result += board[r][c] + "|";
     }
     
     // remove the extra bar
     result = result.substring(0, result.length()-1)
      + '\n';
     
     // add characters to separate the rows
     if(r != BOARD_SIZE -1) {
       for(int c= 0; c < BOARD_SIZE; c++) {
         result += "_ ";
       }
        result += '\n';
     }
    
   }
    return result;
  }
  
  /**
   * Check for a winner across the rows.
   */
  public char rowWinner() {
    boolean didWin = true;
    
    for(int r = 0; r < BOARD_SIZE; r++) {
      didWin = true;
      for(int c = 0; c < BOARD_SIZE - 1; c++) {
        if(board[r][c] != board[r][c+1] 
           || board[r][c] == BLANK_SQUARE) {        
          didWin = false;
        }
      }

      if(didWin) {
        return board[r][BOARD_SIZE-1];
      }
    }
    return '\0';
  }
  
  /**
   * Check for a winner down the columns.
   */
  public char colWinner() {
    boolean didWin = true;
    
    for(int c = 0; c < BOARD_SIZE; c++) {
      didWin = true;
      for(int r = 0; r < BOARD_SIZE - 1; r++) {
        if(board[r][c] != board[r+1][c] 
           || board[r][c] == BLANK_SQUARE) {        
          didWin = false;
        }
      }

      if(didWin) {
        return board[BOARD_SIZE-1][c];
      }
    }
    return '\0';
  }
  
  /**
   * Check for a winner on the diagonals. 
   */
  public char winDiagonals() {
    boolean didWin = true;
    
    // upper-left to lower-right diagonal
    for(int r = 0; r < BOARD_SIZE - 1; r++) {
      if(board[r][r] != board[r+1][r+1] 
           || board[r][r] == BLANK_SQUARE) {
        didWin = false;
      }
      
      if (didWin) {
        return board[BOARD_SIZE-1][BOARD_SIZE-1];
      }
    }
    
    // upper-right to lower-left diagonal
    for(int r = 0; r < BOARD_SIZE - 1; r++) {
      if(board[r][BOARD_SIZE-1-r] 
         != board[r+1][BOARD_SIZE-2-r] 
           || board[r][BOARD_SIZE-1-r] 
           == BLANK_SQUARE) {
        didWin = false;
      }
      
      if (didWin) {
        return board[r][BOARD_SIZE-1-r];
      }
    }
    
    return '\0';
  }
  
  /** 
   * Return the winning character or if there is no
   * winner return '\0'.
   */ 
  public char whoWon() {
    if(rowWinner() != '\0') {
      return rowWinner();
    } else if (colWinner() != '\0') {
      return colWinner();
    } else if (winDiagonals() != '\0') {
      return winDiagonals();
    } 
    return '\0';
  }
  
  /** Return whether there is a draw or not. */
  public boolean isDraw() {
  
    // if nobody has won
    if(whoWon() == '\0') {

      // check for a draw
      for(int r = 0; r < BOARD_SIZE; r++ ) {
        for(int c = 0; c < BOARD_SIZE; c++) {
          if(board[r][c] == BLANK_SQUARE) {
            return false;
          }
        }
      }
      return true;
    } else {
      return false;
    }
  }
  
  
}
  
