001package ca.bc.webarts.examples;
002/**
003 * From http://www.coderslexicon.com/a-beginner-tic-tac-toe-class-for-java/
004 **/
005public class TicTacToe
006{
007
008  private char[][] board;
009  private char currentPlayerMark;
010
011  public TicTacToe()
012  {
013    board = new char[3][3];
014    currentPlayerMark = 'x';
015    initializeBoard();
016  }
017
018
019  // Set/Reset the board back to all empty values.
020  public void initializeBoard()
021  {
022
023    // Loop through rows
024    for (int i = 0; i < 3; i++)
025    {
026
027      // Loop through columns
028      for (int j = 0; j < 3; j++)
029      {
030        board[i][j] = '-';
031      }
032    }
033  }
034
035
036  // Print the current board (may be replaced by GUI implementation later)
037  public void printBoard()
038  {
039    System.out.println("-------------");
040
041    for (int i = 0; i < 3; i++)
042    {
043      System.out.print("| ");
044      for (int j = 0; j < 3; j++)
045      {
046        System.out.print(board[i][j] + " | ");
047      }
048      System.out.println();
049      System.out.println("-------------");
050    }
051  }
052
053
054  // Loop through all cells of the board and if one is found to be empty (contains char '-') then return false.
055  // Otherwise the board is full.
056  public boolean isBoardFull()
057  {
058    boolean isFull = true;
059
060    for (int i = 0; i < 3; i++)
061    {
062      for (int j = 0; j < 3; j++)
063      {
064        if (board[i][j] == '-')
065        {
066          isFull = false;
067        }
068      }
069    }
070
071    return isFull;
072  }
073
074
075  // Returns true if there is a win, false otherwise.
076  // This calls our other win check functions to check the entire board.
077  public boolean isWinner()
078  {
079    return (checkRowsForWin() || checkColumnsForWin() || checkDiagonalsForWin());
080  }
081
082
083  // Loop through rows and see if any are winners.
084  private boolean checkRowsForWin()
085  {
086    for (int i = 0; i < 3; i++)
087    {
088      if (checkRowCol(board[i][0], board[i][1], board[i][1]) == true)
089      {
090        return true;
091      }
092    }
093    return false;
094  }
095
096
097  // Loop through columns and see if any are winners.
098  private boolean checkColumnsForWin()
099  {
100    for (int i = 0; i < 3; i++)
101    {
102      if (checkRowCol(board[0][i], board[1][i], board[2][i]) == true)
103      {
104        return true;
105      }
106    }
107    return false;
108  }
109
110
111  // Check the two diagonals to see if either is a win. Return true if either wins.
112  private boolean checkDiagonalsForWin()
113  {
114    return ((checkRowCol(board[0][0], board[1][1], board[2][2]) == true) || (checkRowCol(board[0][2], board[1][1], board[2][0]) == true));
115  }
116
117
118  // Check to see if all three values are the same (and not empty) indicating a win.
119  private boolean checkRowCol(char c1, char c2, char c3)
120  {
121    return ((c1 != '-') && (c1 == c2) && (c2 == c3));
122  }
123
124
125  // Change player marks back and forth.
126  private void changePlayer()
127  {
128    if (currentPlayerMark == 'x')
129    {
130      currentPlayerMark = 'o';
131    }
132    else
133    {
134      currentPlayerMark = 'x';
135    }
136  }
137
138
139  // Places a mark at the cell specified by row and col with the mark of the current player.
140  public boolean placeMark(int row, int col)
141  {
142
143    // Make sure that row and column are in bounds of the board.
144    if ((row >= 0) && (row < 3))
145    {
146      if ((col >= 0) && (col < 3))
147      {
148        if (board[row][col] == '-')
149        {
150          board[row][col] = currentPlayerMark;
151          return true;
152        }
153      }
154    }
155
156    return false;
157  }
158
159
160  /**
161    * Toms Main method to show how to use this class in a simple console app.
162  **/
163  public static void main(String[] args)
164  {
165    // Create game and initialize it.
166    // First player will be 'x'
167    TicTacToe game = new TicTacToe();
168    game.initializeBoard();
169
170    String player1Play = "";
171    String player2Play = "";
172
173    // Read commands from the console
174    //Loop Until "quit"
175    java.util.Scanner scanIn = new java.util.Scanner(System.in);
176    boolean validRead = false;
177    boolean quit = false;
178    String [] rowCol = null;
179    int currRow = 0;
180    int currCol = 0;
181
182    System.out.println("\nTic Tac Toe\n=========");
183    while (!quit)
184    {
185      // Player 1 Move
186      // ************
187      validRead = false;
188      while (!quit && !validRead)
189      {
190        System.out.print("Player1 Place Your 'x':  row,column ? ");
191        player1Play = scanIn.nextLine();
192        rowCol = player1Play.split("\\,");
193          System.out.println("player1Play="+player1Play);
194          System.out.println("rowCol.length="+rowCol.length);
195
196        try
197        {
198          if (rowCol.length == 2)
199          {
200            currRow = Integer.parseInt(rowCol[0]);
201            currCol = Integer.parseInt(rowCol[1]);
202            validRead = true;
203          }
204          else
205            if (rowCol.length == 1 && rowCol[0].equalsIgnoreCase("quit"))
206              quit = true;
207            else
208              System.out.println("Placemark must be 2 integers in the form:  row,col");
209        }
210        catch (Exception ex)
211        {
212          System.out.println("Placemark must be 2 integers.");
213          validRead = false;
214        }
215      }
216
217      if (!quit)
218      {
219        // Player 'x' places a mark in the top right corner row 0, column 2
220        // These values are based on a zero index array, so you may need to simply take in a row 1 and subtract 1 from it if you want that.
221        game.placeMark(currRow,currCol);
222
223        // print the board
224        game.printBoard();
225
226        // Did we have a winner?
227        if (game.isWinner())
228        {
229           System.out.println(" ! ! We have a winner! Congrats Player 1!\n\nPlay Again (type 'quit' to end)");
230           game.initializeBoard();
231           validRead = true;// this bypasses Player 2 and jumps straight to NEXT game
232        }
233        else if (game.isBoardFull())
234        {
235           System.out.println(" > > Appears we have a draw!\n\nPlay Again (type 'quit' to end)");
236           game.initializeBoard();
237           validRead = true; // this bypasses Player 2 and jumps straight to NEXT game
238        }
239        else // just move to Player2
240          validRead = false;
241
242        game.changePlayer();
243
244        // Player 2 Move
245        // ************
246        while (!quit && !validRead)
247        {
248          System.out.print("Player2 Place Your 'y':  row,column ? ");
249          player2Play = scanIn.nextLine();
250          rowCol = player2Play.split("\\,");
251          try
252          {
253            if (rowCol.length == 2)
254            {
255              currRow = Integer.parseInt(rowCol[0]);
256              currCol = Integer.parseInt(rowCol[1]);
257              validRead = true;
258            }
259            else
260              if (rowCol.length == 1 && rowCol[0].equalsIgnoreCase("quit"))
261                quit = true;
262              else
263                System.out.println("Placemark must be 2 integers in the form:  row,col");
264          }
265          catch (Exception ex)
266          {
267            System.out.println("Placemark must be 2 integers.");
268            validRead = false;
269          }
270        }
271        if (!quit)
272        {
273          // Player 'x' places a mark in the top right corner row 0, column 2
274          // These values are based on a zero index array, so you may need to simply take in a row 1 and subtract 1 from it if you want that.
275          game.placeMark(currRow,currCol);
276
277          // print the board
278          game.printBoard();
279
280          // Did we have a winner?
281          if (game.isWinner())
282          {
283             System.out.println(" ! ! We have a winner! Congrats Player 1!\n\nPlay Again (type 'quit' to end)");
284             game.initializeBoard();
285             validRead = true;// this bypasses Player 2 and jumps straight to NEXT game
286          }
287          else if (game.isBoardFull())
288          {
289             System.out.println(" > > Appears we have a draw!\n\nPlay Again (type 'quit' to end)");
290             game.initializeBoard();
291             validRead = true; // this bypasses Player 2 and jumps straight to NEXT game
292          }
293          else // just move to Player2
294            validRead = false;
295
296          game.changePlayer();
297        }
298      }
299    }    // Repeat steps again for placing mark and checking game status...
300
301
302    System.out.println(" Bye.");
303    scanIn.close();
304  }// main
305
306}
307