CS 161 Homework 8 - Tic-Tac-Toe
Due Mon Nov 25 at 11:59pm
Overview
In this assignment, you will be making another computer version of a simple game: in this case, Tic Tac Toe. While you are actually perfectly capable of enabling a computer to play (and win!) at this game, for this assignment you will just be making a graphical program that allows two humans sitting at the same computer to play together.
Your program will present the player with a window containing 9 buttons--one button for each spot on the grid. Players will take turns making their moves by clicking buttons. Note that the game should make sure the players don't select an invalid move! If one player gets three-in-a-row, the program will congratulate them with a pop-up window, such as:
Once a player has won (or there are no more possible moves), the game resets for the next round.
This assignment should be completed individually. You are welcome to ask for help (either from me or from your classmates), but remember the Gilligan's Island rule!Objectives
- To practice implementing Graphical User Interfaces (GUIs) using classes from the Swing libraries
- To practice writing graphical event-driven programs
- To practice developing programs with separated logic and representation
Necessary Files
You will be creating your own program from scratch for this assignment! Details on the classes you will be creating are below.
You will need to download a copy of the README.txt (right-click on the link and select "Save Link As" to download the file) to fill out and turn in along with your assignment. Be sure and place a completed version of this file in your project folder before you upload it!
Assignment Details
This assignment is smaller and simpler than the previous ones, but you have less time to complete it in. Be sure and get started ASAP, and make sure to add a little bit of functionality each day.
For this assignment you will be implementing two classes. The first, TicTacToeGame
will be a class that models a game of tic-tac-toe. This class will be similar it functionality to your HangmanGame class from the previous homework, except that you won't have a "game loop" like you did with the playGame()
method (instead, each "turn" of the game will be executed by clicking buttons in the interface). The second class, TicTacToeFrame
will provide a graphical interface to your TicTacToeGame
--it will be able to call methods on the game when players take turns or to figure out what should be displayed.
Note that all your "game" logic should go in the TicTacToeGame
class, and all our your input/output should go in the TicTacToeFrame
class. In effect, you should be able to play the TicTacToeGame without needing the frame (by calling the proper methods).
You can complete these classes in either order--you can even complete them simultaneously, adding methods to both. You can also easily create the TicTacToeGame class and test that to perfection, then add in the Frame.
TicTacToeGame
This class will model the game of tic-tac-toe. It should keep track of the board (the grid of letters), as well as which player's turn it is.
- Think about what instance variables you would use to represent these attributes, as well as how you would initialize them in the constructor! Are there any other attributes you might need?
Your class should include the following methods:
-
A
getPlayer()
method and agetSquare()
method that are able to return information about the game.getPlayer()
should return a String representing which player is currently "up", andgetSquare()
should return a String representing the current letter for a square at a given row and column. -
A
makeMove()
method that has the current player place their mark on the square at the given row and column. This method will need to update the board AND THEN jump switch to the other player in preparation of the next move. The method should also return whether or not the move was legal--a move is illegal if another player has already played there! -
A
getWinner()
method that returns A String representing the current winner of the game, if any. This will be the most complicated method of the class, because it will need to perform the logic that sees if anyone got three in a row.- It is possible to either loop through the grid to determine whether there is a three in a row, or to just use a number of well-written if statements. Think carefully through this logic, and test it carefully!
- If the game is a tie (because the entire board is full), then you should return something like "No one" as the winner.
- If there is no winner but the game is not finished, this method should return
null
. This makes it easy to see if the game is finished (you can simply askif(getWinner() == null)
).
-
A
clear()
method that resets the board and the player for a new game. Note that this method is a bit like your HangmanGame'sreset()
method--you may also want to call this from the constructor rather than duplicating code!
TicTacToeFrame
This class will provide the graphical interface for your TicTacToeGame
class.
-
This class should extend the
JFrame
class found in thejavax.swing.*;
package. That is, this class will actually be aJFrame
, and so have all the methods that you've called onJFrame
s in the past!-
Thus your constructor for this class will want to call methods such as
this.setTitle()
,this.setDefaultCloseOperation()
, etc. Remember to callthis.setVisible(true)
to make sure your Frame appears!
-
Thus your constructor for this class will want to call methods such as
-
Note that your constructor should instantiate a new
TicTacToeGame
object. Because the object is a core attribute of yourTicTacToeFrame
, should it be a local or an instance variable? -
Your constructor will also need to set up the buttons for the game. You will need a
JButton
object to represent each button on the board.- Since you will have a grid of buttons, it would make a lot of sense to put the buttons into an array of some sort, rather than having 9 different variables. Making the buttons inside a loop will save you a lot of code rewriting!
-
You will also need to organize your buttons into a grid. To do this, you should instantiate a new
JPanel
object to act as a "container" for the buttons. You can give this JPanel aGridLayout
and thenadd
the buttons to the JPanel in order to easily organize them into a grid. Remember to add the button's panel to your JFrame--that is, yourTicTacToeFrame
you are constructing- Use the JPanel's
setPreferredSize()
method to make sure that your overall container (and the buttons inside of it) aren't tiny. Callingpack()
on the JFrame will tell Java to try and match the preferred sizes you specify.
- Use the JPanel's
-
Note you can specify how the text on the buttons look by instantiating a new
Font
object and applying this Font to the buttons with thesetFont()
method.
-
In order to have your JButtons actually do something, you'll need to add event handling--you need to make it so your program responds to button press events. Recall that there are three steps to add event handling:
- Implement the
ActionListener
interface (be sure to define the required method! You can start by just adding the method signature and leaving the method itself empty). - Register the listener for every button using the
addActionListener()
method. Remember thatthis
TicTacToeFrame is the ActionListener! - Fill in the
actionPerformed()
method to respond to each button being pressed. You can use thegetSource()
method of the ActionEvent parameter to figure out which button was pressed!
Refer to the notes form class for examples of how to add event handling.
-
Helpful hint:
Add a simple print statement to the
actionPerformed()
method, so that you can test that pressing your buttons calls the method as expected.
- Implement the
-
Now that you have your buttons layed out and firing events, you should add code that makes the buttons play the game. This is not too complicated. When the
actionPerformed()
method is called, you'll need to figure out which button caused the event to occur--you can do this by searching your array of buttons for the button that match's the eventsgetSource()
. Once you've found that button, you'll need to do a few things: First, tell the underlyingTicTacToeGame
that the current player made a move at the button's position. Next, check to make sure that move was legal (note: the game'smakeMove()
method should return whether the move was legal). If it wasn't legal, you'll want to alert the player (see below) so they can try again. If the move was legal, you'll want to change the button's label using thesetText()
method. You'll then need to ask the game if there is a winner (or the game is over). If it is, then you should show a message congratulating the player, then reset the board for the next game (and clear the labels of all the buttons).- There is a lot of functionality here; breaking out some of the code (i.e., the "check for a winner" functionality) into a helper method could be nice.
-
You won't want to print messages to the player, since we're using a GUI program and not the command line. Instead, you can easily show a nice popup window using the static methods from the
JOptionPane
class. For example, you can make a simple popup message with the
showMessageDialog()
method. This method can take a number of parameters to define its behavior: a simple example is:
JOptionPane.showMessageDialog(null, "Hello world!", "An example", JOptionPane.PLAIN_MESSAGE);
Try out the above code and study the documentation to figure out what parameters you will need to give this method. - Be sure and test your program thoroughly. Try lots of different games: winning with either player, winning with different three-in-a-row lines, getting a stalemate, etc.
Extensions
There are a number of other extensions you could add for fun. However, no extra credit is available on this assignment.
-
You might start the game by prompting the players for their names, and then using those instead of X and O (or at least congratulating the players directly). You can get input from the user in a GUI program by using another
JOptionPane
method:JOptionPane.showInputDialog("message you want to display to the user");
This method will return a String (just like using the .nextLine() method of Scanner!)
- Can you modify your program so that the size of the board is a variable? For example, perhaps your class' constructors take in a "number of rows" parameter, and then you use that variable for size. This would let you easily specify a 4x4 or 5x5 tic-tac-toe board. Note that this makes the checking for a winner code slightly more complicated--but if you write your loops carefully you can do it.
Submitting Your Assignment
- Be sure and test your program thoroughly to make sure it works. Make sure it is documented with lots and lots of informative comments!
- Remember to fill out the README.txt file!
- Upload the entire project directory (including all Java files, as well as the README.txt) to the Hwk8 submission folder on the hedwig server. Make sure you upload your work to the correct folder!.
- This assignment is due at 11:59pm on Mon, Nov 25.
Grading
This assignment will be graded on approximately the following criteria:
- Your program displays a JFrame with a grid of buttons [20%]
- Your program responds to the button pressed appropriately (i.e., changing the button label) [15%]
- Your program reports when a player makes an illegal move [5%]
- Your program keeps track of moves that have been made and the current player's turn [10%]
- Your program reports when a player has won the game, or when the game is a stalemate [15%]
- Your game resets after a winner has been determined [10%]
- Your code is carefully documented, with full Javadoc methods and inline comments [10%]
- Your code adheres to proper style guidelines. This means that variables are given descriptive names, local variables aren't specified as instance variables, you use return values and parameters to move data between methods, etc. Look over notes from previous assignments and labs for some guidance. If you have any specific questions about good style, please ask me! Note that this also includes keeping code properly separated between the Game and the Frame classes [10%]
- You have completed the included README.txt file [5%]