// Project 5. Question 2. Solution
// Tic Tac Toe (with arrays)
//   modified from the Project 3.
// Date: 25 March 2001
// Author: Rimon Barr

class TicTacToe {

  // constants for player pieces and numbers
  private static final char[] PLc={'X', 'O'};
  private static final int[] PLn={1, 2};
  private static final char EMPTY=' ';

  // board (row, col)
  private static final int SIZE=3;
  private static char[][] sq=new char[SIZE][SIZE];

  // input stream
  private static TokenReader in=new TokenReader(System.in);

  // display board
  private static void printLine() {
    for(int i=0; i<SIZE; i++)
      System.out.print("+---");
    System.out.println("+");
  }
  public static void printBoard() {
    printLine();
    for(int i=0; i<SIZE; i++) {
      for(int j=0; j<SIZE; j++)
        System.out.print("| "+sq[i][j]+" ");
      System.out.println("|");
      printLine();
    }
  }

  // reset the board
  public static void clearBoard() {
    for(int i=0; i<SIZE; i++)
      for(int j=0; j<SIZE; j++)
        sq[i][j]=EMPTY;
  }

  // determine whether the board is filled
  public static boolean isBoardFull() {
    for(int i=0; i<SIZE; i++)
      for(int j=0; j<SIZE; j++)
        if(sq[i][j]==EMPTY)
          return false;
    return true;
  }

  // determine whether position is within board limits
  public static boolean isValidPos(int row, int col) {
    return row>=0 && row<SIZE && col>=0 && col<SIZE;
  }

  // check if a given player has won
  public static boolean hasPlayerWon(char player) {
    // (We use literals and not counters to SIZE in all places, 
    //  because it's difficult to generalise the rules of tic-tac-toe.
    //  Only use loops when it makes coding clearer / easier.)

    // columns
    for(int col=0; col<SIZE; col++)
      if (sq[0][col]==player && sq[1][col]==player && sq[2][col]==player) 
        return true;
    // rows
    for(int row=0; row<SIZE; row++)
      if (sq[row][0]==player && sq[row][1]==player && sq[row][2]==player) 
        return true;
    // diagonals
    if (sq[0][0]==player && sq[1][1]==player && sq[2][2]==player) return true;
    if (sq[2][0]==player && sq[1][1]==player && sq[0][2]==player) return true;
    // exhausted all winning possibilities
    return false;
  }

  // determine whether the game is over
  public static boolean isGameOver() {
    return isBoardFull() || hasPlayerWon(PLc[0]) || hasPlayerWon(PLc[1]);
  }

  // play one game
  public static boolean playGame() {
    System.out.println("New Game.");
    // variables for input and turn counter
    String input="";
    int turn=0;
    // reset board
    clearBoard();
    // play game until its over or user asks to quit
    while (!isGameOver() && !input.equals("99")) {
      // display board
      printBoard();
      // set pln and plc according to turn
      int pln=PLn[turn%2];
      char plc=PLc[turn%2];
      // ask for input
      System.out.print("Player "+pln+" turn: ");
      input=in.readLine();
      // check for quit
      if(input==null || input.equals("99")) break;
      // validate input
      if(input.length()!=2) {
        System.out.println("Expected two characters.");
        continue;
      }
      int row=input.charAt(0)-'1';
      int col=input.charAt(1)-'1';
      if (!isValidPos(row, col)) {
        System.out.println("Invalid position.");
        continue;
      }
      // check that position is empty
      if (sq[row][col]!=EMPTY) {
        System.out.println("Position already taken. Please try again.");
        continue;
      }
      // put piece on board
      sq[row][col]=plc;
      // increment turn counter
      turn++;
    }
    // determine how the game ended
    System.out.println("Final board:");
    printBoard();
    if (hasPlayerWon(PLc[0]))
      System.out.println("Player "+PLn[0]+" won.");
    else if (hasPlayerWon(PLc[1]))
      System.out.println("Player "+PLn[1]+" won.");
    else if (isBoardFull())
      System.out.println("Draw.");
    else {
      System.out.println("Game not completed.");
      return false; // do not play another game
    }
    return true; // play another game
  }

  // program entry point
  public static void main(String[] args) {
    // introduction
    System.out.println("Welcome to Tic Tac Toe.");
    System.out.println("Please enter positions as 'rc' (r - row, c - col), or 99 to exit");
    // play loop
    while(playGame());
    // say goodbye
    System.out.println("Thanks for playing. Come again.");
  }
}
