- Now that we have a working board, we need a way to mark a cell
- To do this we will define a mark_cell
method in TicTacToeBoard that takes
3 parameters
- The row number
- The column number
- The mark to be placed in the cell
- But we don't want to do this if any of the parameters are invalid
- So we will create a method move_good
to check the argument
- There are 4 ways the parameters can be wrong
- The row number can be out of bounds
- The column number can be out of bounds
- The mark may not be a legal character
- The cell may already be occupied
- If there is a problem with any of the values this method will throw
an
IllegalArgumentException
- To make this work we need we need two constants
private final char USER_MARK = 'X';
private final char MACHINE_MARK = 'O';
- mark_cell simply calls mark_good
- And changes the character in the cell if it can
public void mark_cell(int row, int col, char mark) throws IllegalArgumentException {
move_good(row, col, mark);
board[row][col] = mark;
}
- move_good has more work to do
private void move_good(int row, int col, char mark) throws IllegalArgumentException {
if (row < 0 || row > 2){
throw new IllegalArgumentException(row + " is not a valid row number");
} else if (col < 0 || col > 2) {
throw new IllegalArgumentException(col + " is not a valid column number");
} else if (mark != USER_MARK && mark != MACHINE_MARK) {
throw new IllegalArgumentException(mark + " is not a valid mark");
} else if (board[row][col] != ' ') {
throw new IllegalArgumentException("The square " + row + "," + col + " is occupied");
}
}
- And here is
public class TicTacToe {
public static void main (String[] args){
TicTacToeBoard board = new TicTacToeBoard();
System.out.println(board);
board.mark_cell(1,1, 'X');
System.out.println(board);
try {
board.mark_cell(3,1,'X');
} catch (Exception e1) {
System.out.println(e1.getMessage());
}
try {
board.mark_cell(2,3,'X');
} catch (Exception e2) {
System.out.println(e2.getMessage());
}
try {
board.mark_cell(2,2,'Z');
} catch (Exception e2) {
System.out.println(e2.getMessage());
}
try {
board.mark_cell(1,1,'X');
} catch (Exception e2) {
System.out.println(e2.getMessage());
}
}
}
$ java TicTacToe
| |
------
| |
------
| |
| |
------
|X|
------
| |
3 is not a valid row number
3 is not a valid column number
Z is not a valid mark
The square 1,1 is occupied
- You can see the code for this version of TicTacToeBoard
here
- There are three ways a player can win the game
- Fill a row with their mark
- Fill a column with their mark
- Fill a diagonal with their mark
- The code will have to have three sections
- One for each of the different ways to win
- But before we do this we have to create the helper method cell_has_mark
- Which simply returns
true
if a cell has a specific mark
private boolean cell_has_mark(int row, int col, char mark) {
return board[row][col] == mark;
}
- The section of code checking for row completion has a
for
that checks each column in the row
// check rows
for (int row = 0; row <= 2; row++){
if (cell_has_mark(row, 0, mark) && cell_has_mark(row, 1, mark) && cell_has_mark(row, 2, mark)){
return true;
}
}
- The column check code is similar
// check columns
for (int col = 0; col <= 2; col++){
if (cell_has_mark(0, col, mark) && cell_has_mark(1, col, mark) && cell_has_mark(2, col, mark)){
return true;
}
}
- The last test section checks each diagonal
// check diagonals
if (cell_has_mark(0, 0, mark) && cell_has_mark(1, 1, mark) && cell_has_mark(2, 2, mark)){
return true;
} else if (cell_has_mark(0, 2, mark) && cell_has_mark(1, 1, mark) && cell_has_mark(2, 0, mark)) {
return true;
}
- If all the checks fail the method returns
false
- We need to app several times to check each possibility
$ java TicTacToe
| |
------
| |
------
| |
Next move (row col): 1 1
| |
------
|X|
------
| |
|O|
------
|X|
------
| |
Next move (row col): 0 1
The square 0,1 is occupied
Next move (row col): 1 0
|O|
------
X|X|
------
| |
|O|
------
X|X|
------
| |
Next move (row col): 1 2
|O|
------
X|X|X
------
| |
User wins!
$ java TicTacToe
| |
------
| |
------
| |
Next move (row col): 1 1
| |
------
|X|
------
| |
O| |
------
|X|
------
| |
Next move (row col): 0 1
O|X|
------
|X|
------
| |
O|X|
------
O|X|
------
| |
Next move (row col): 2 1
O|X|
------
O|X|
------
|X|
User wins!
$ java TicTacToe.java
| |
------
| |
------
| |
Next move (row col): 1 1
| |
------
|X|
------
| |
|O|
------
|X|
------
| |
Next move (row col): 0 0
X|O|
------
|X|
------
| |
X|O|
------
O|X|
------
| |
Next move (row col): 2 2
X|O|
------
O|X|
------
| |X
User wins!
- You can see the code for this version of TicTacToe
and TicTacToeBoard
here and
here