/**-- TIC TAC TOE ------------------------------------------------------**\
 This program implements a basic TIC-TAC-TOE game.
 So far, it only recognizes a winning position if
 there are 3-in-a-row in a VERTICAL column.
 Try these practice exercises:
 (1) Play a game where X wins.
 (2) Play a game which ends in a DRAW.
 (3) Play a game where O wins.
 (4) Add more "else if" conditions for other winning positions.
 (5) Find an ERROR in the program, and add code (if..)
     to prevent the error from occuring.
 (6) Repeat #5 until perfect.
\**---------------------------------------------------------------------**/

public class TicTacToe
{ public static void main(String[] args)
  { new TicTacToe();}

  String[][] board = new String[3][3];

  public TicTacToe()
  { clearBoard();
    showBoard();
    do
    {
      inputMove();
      showBoard();
    } while(winner() == -1);

    if (winner() == 0)
    { output("Draw"); }
    else if (winner() == 1)
    { output("X wins"); }
    else if (winner() == 2)
    { output("O wins"); }

    input("---- press [enter] ----");
  }

/**-- Clear Board ------------------------------------------------------**\
   The game stars with a "*" in each square.
\**---------------------------------------------------------------------**/

  void clearBoard()
  { board[0][0] = "*";
    board[0][1] = "*";
    board[0][2] = "*";
    board[1][0] = "*";
    board[1][1] = "*";
    board[1][2] = "*";
    board[2][0] = "*";
    board[2][1] = "*";
    board[2][2] = "*";
  }

/**-- Show Board -------------------------------------------------------**\
   Displays the board after each move.
   This could have been written with loops.
\**---------------------------------------------------------------------**/

  void showBoard()
  { output(board[0][0] + "  " + board[0][1] + "  " + board[0][2]);
    output("");
    output(board[1][0] + "  " + board[1][1] + "  " + board[1][2]);
    output("");
    output(board[2][0] + "  " + board[2][1] + "  " + board[2][2]);
    output("");
  }

/**-- Input Move -------------------------------------------------------**\
   User types two numbers to input a move.     0,0 | 0,1 | 0,2
   Here are the coordinates:                  -----+-----+-----
                                               1,0 | 1,1 | 1,2
                                              -----+-----+-----
                                               2,0 | 2,1 | 2,2
\**---------------------------------------------------------------------**/

  void inputMove()
  { String player = input("Player (X or O)?");
    int row = inputInt("Row?");
    int col = inputInt("Col?");
    board[row][col] = player;
  }

/**-- Winner -----------------------------------------------------------**\
   Checks whether the game is over,
   Returns a number indicating the winner:
      -1 --> game is not over
       0 --> draw
       1 --> X wins
       2 --> O wins
\**---------------------------------------------------------------------**/

  int winner()
  { if (!board[0][0].equals("*") &&
        !board[0][1].equals("*") &&
        !board[0][2].equals("*") &&
        !board[1][0].equals("*") &&
        !board[1][1].equals("*") &&
        !board[1][2].equals("*") &&
        !board[2][0].equals("*") &&
        !board[2][1].equals("*") &&
        !board[2][2].equals("*")   )
    { return 0; }
    else if(board[0][0].equals("X") &&
            board[1][0].equals("X") &&
            board[2][0].equals("X")
        ||  board[0][1].equals("X") &&
            board[1][1].equals("X") &&
            board[2][1].equals("X")
        ||  board[0][2].equals("X") &&
            board[1][2].equals("X") &&
            board[2][2].equals("X")
           )
    { return 1; }
    else if(board[0][0].equals("O") &&
            board[1][0].equals("O") &&
            board[2][0].equals("O")
        ||  board[0][1].equals("O") &&
            board[1][1].equals("O") &&
            board[2][1].equals("O")
        ||  board[0][2].equals("O") &&
            board[1][2].equals("O") &&
            board[2][2].equals("O")
           )
    { return 2; }
    else
    { return -1; }
  }

/**-- EZ IO ------------------------------------------------------------**\
  Simple methods for console input and output.
\**---------------------------------------------------------------------**/

  static void output(String info)
  {  System.out.println(info);
  }

  static void output(double info)
  {  System.out.println(info);
  }

  static void output(long info)
  {  System.out.println(info);
  }

  static int inputInt(String Prompt)
  {  int result=0;
     try{result=Integer.parseInt(input(Prompt).trim());}
     catch (Exception e){result = 0;}
     return result;
  }

  static double inputDouble(String Prompt)
  {  double result=0;
     try{result=(new Double(input(Prompt).trim())).doubleValue();}
     catch (Exception e){result = 0;}
     return result;
  }

  static String input(String prompt)
  {  String inputLine = "";
     System.out.print(prompt);
     try
      {inputLine = (new java.io.BufferedReader(
                    new java.io.InputStreamReader(System.in))).readLine();}
     catch (Exception e)
      { String err = e.toString();
        System.out.println(err);
      }
     return inputLine;
  }
}