package tictactoepkg;

public class TicTacToe {
  public static final char EMPTY = ' ';
  public static final char DRAW = 'D';
  public static final char NOWINNER = 'N';
  public static final char XTURN = 'X';
  public static final char OTURN = 'O';
  private static final int DEFAULT_BOARDSIZE = 3;
  private int boardSize;
  private char winner;
  private int numberMoves;
  private char[][] board;
  private boolean nextTurn; // true for 'X'

  public TicTacToe() {
    this(DEFAULT_BOARDSIZE);
  }

  public TicTacToe(int size) {
    boardSize = size;
    winner = 'N';
    numberMoves = 0;
    nextTurn = true;
    board = new char[boardSize][boardSize];
    for (int i = 0; i < board.length; i++)
      for (int j = 0; j < board[i].length; j++)
        board[i][j] = EMPTY;
  }

  public int getBoardSize() {
    return boardSize;
  }

  public int getNumberMoves() {
    return numberMoves;
  }

  public char getTurn() {
    if (nextTurn)
      return XTURN;
    else
      return OTURN;
  }

  public char getWinner() {
    return winner;
  }

  public boolean move(int x, int y) {
    if (x < 0 || x >= boardSize || y < 0 || y >= boardSize ||
        board[x][y] != EMPTY || winner != NOWINNER)
      return false;
    if (nextTurn)
      board[x][y] = XTURN;
    else
      board[x][y] = OTURN;
    nextTurn = !nextTurn;
    numberMoves++;
    setWinner();
    return true;
  }

  public String toString() {
    StringBuffer buf = new StringBuffer(getClass().getName() +
          "[boardSize=" + boardSize + ",winner=" + winner +",numberMoves="
          + numberMoves +",nextTurn=" + nextTurn + "]\nboard:\n");
    for (int i = 0; i < board.length; i++) {
      for (int j = 0; j < board[i].length; j++)
        buf.append(board[i][j] + "  ");
      buf.append("\n");
    }
    return buf.toString();
  }

  private boolean backDiagonalWinner() {
    char test = board[0][boardSize - 1];
    if (test == EMPTY)
      return false;
    for (int i = 1; i < boardSize; i++)
      if (test != board[i][boardSize - 1 - i])
        return false;
    winner = test;
    return true;
  }

  private boolean columnWinner(int col) {
    char test = board[0][col];
    if (test == EMPTY)
      return false;
    for (int i = 1; i < boardSize; i++)
      if (test != board[i][col])
        return false;
    winner = test;
    return true;
  }

  private boolean forwardDiagonalWinner() {
    char test = board[0][0];
    if (test == EMPTY)
      return false;
    for (int i = 1; i < boardSize; i++)
      if (test != board[i][i])
        return false;
    winner = test;
    return true;
  }

  private boolean rowWinner(int row) {
    char test = board[row][0];
    if (test == EMPTY)
      return false;
    for (int i = 1; i < boardSize; i++)
      if (test != board[row][i])
        return false;
    winner = test;
    return true;
  }

  private void setWinner() {
    if (winner != NOWINNER)
      return;
    if (forwardDiagonalWinner() || backDiagonalWinner())
      return;
    for (int i = 0; i < boardSize; i++)
      if (rowWinner(i) || columnWinner(i))
        return;
    if (numberMoves == boardSize*boardSize)
      winner = DRAW;
  }
  
  public String getBoardString() {
          String s;
          s = "";
          for (int i = 0; i < boardSize; i++) {
            for (int j = 0; j < boardSize; j++) {
              s = s + " " + board[i][j] + " ";
              if (j < boardSize - 1)
                s = s + "|";
            }
            s = s + "\n";
            if (i < boardSize - 1) {
              for (int j = 0; j < boardSize; j++) {
                s = s + "---";
                if (j < boardSize - 1)
                  s = s + "|";
              }
              s = s + "\n";
            }
          }
          return s;
        }
  }


