We are going to create a program to play Tic-Tac-Toe, a two-player game that is played on a 3 x 3 grid where a player wins by placing three of his or her markers in a row. If you are unfamiliar with the game or need a refresher, feel free to browse the Wikipedia article.
Design your game layout. The image shown on the right is just an example, and we encourage you to tweak the layout and look to your liking. At minimum, you will need the following:
We suggest that you create a separate function to draw your board, possibly named
drawBoard()
, that will be called from draw()
.
If you would like to, you can also parameterize this function to make your code more flexible should
you choose to later alter your layout.
We will need to declare and initialize some variables to keep track of the current "state" of the game. You will definitely need to track the state of the board (i.e. who has played what and where), which we suggest you do using an array of size 9. The following questions are meant to help you think about the state of the game, though the exact implementation is up to you:
Before we implement user input, let's make sure we can display the correct symbols on our grid. You should have an array of size 9 that holds the current state of the board. We recommend using the following layout to relate the board to the array:
Array index: [ 0 | 1 | 2 ] [ 3 | 4 | 5 ] [ 6 | 7 | 8 ]
That is, element 4 of your array holds the current state of the middle square of your board, and element 5 of your array holds the current state of the square at row 2, column 3.
Now we need to display symbols to show the player moves ('O' for Player 1, 'X' for Player 2).
Our suggestion is to use a separate char
array:
char[] symbols = {' ','O','X'};
With this in your code, then symbols[0]
will display a space (no symbol),
symbols[1]
will display an 'oh', and symbols[2]
will display an 'ex'.
Make sure that this works well in combination with the values you store in your array.
To do the actual display on your drawing canvas, we recommend using the text()
function
inside of nested for-loops.
The for-loop variables will help you calculate the correct coordinates to pass to
text()
, but you will also need to use them to access the correct index of your game
board state.
We can recognize user clicks using the mousePressed()
function in combination with the
values of mouseX
and mouseY
.
If you are unsure about how to proceed, see the "Puzzle App" lectures or the "Birthday
Visualization" lab.
It is easiest to start with the Reset button.
Create a separate reset()
function to call when the user clicks within the Reset button
region of the drawing canvas.
This should set all of the game state variables to the values they would hold at the very beginning
of a game of Tic-Tac-Toe.
When the user clicks within the game board, your program should correctly identify which square
(0-8) was clicked, similar to how the Birthday Visualization recognized which month and day was
being hovered over.
Write some test code so that you can verify correct behavior using either println()
or
text()
.
Once that is confirmed to be working correctly, you can move on to "playing that square." Remember that we only want to update our game board if (1) the user clicked on a board square and (2) that square hasn't been played previously. Similarly, when do we want to change players?
After each valid play, your program should check to see if the end of the game has been reached (a player wins or there is a draw). Create a separate function to do this.
Endgame conditions can be checked using just the state of the game board. There are certainly some more clever ways to do this, but we are fine with the "brute force" method of checking every possible winning combination one-by-one.
Once the endgame has been reached, your game state should be updated to reflect this. How will this affect gameplay? Should the user still be allowed to play squares on the game board? Note: we still want to allow the user to click the Reset button while at the endgame and then start a new game.
And there you have it! You've put together a working game! Play a few rounds with a partner or friend in order to make sure your program behavior matches what you expect to happen. This is a process called testing that is really important. Make sure you take your program through every possible game state!
A working solution is shown on the right. You do not need to follow this exact layout.
In order to better visualize what's going on, extra code was included to display a mouse symbol in the lower-left corner of the image whenever a mouse button is clicked.
Here's what's being shown in the gif: