CS 51 Laboratory # 12
Pictionary

Objective: To gain experience with Streams.

Networked Pictionary

This week's assignment will give you the opportunity to practice working with Streams in the context of a networked Pictionary program. You are encouraged to work in pairs on this program. You must do all of the coding together. Only turn in one copy of the program, but make sure both of your names are on the folder and at the top of each class.

In Pictionary, one player selects a word or phrase to act out, and another player must guess what the word or phrase is. The only way the player may communicate with the guessing player, though, is by drawing: the one player draws a picture representing the word or phrase, while the other player tries to guess it.

Our networked Pictionary program allows two players to play the game. One is the Drawer; the other is the Guesser. When the program starts up, a window with two buttons appears. The buttons are labeled "Drawer" and "Guesser" to allow the player to select which they will be.

If the player selects Drawer, he or she is asked to select a file from which a card is picked. The card tells the player what to draw. The Drawer's window contains a drawing canvas, the card display, and another label for the Guesser's guess. The Drawer then draws their representation of the word/phrase with the mouse. Guesses appear in the Drawer's window when made by the Guesser (with a return at the end). When the Guesser makes the right guess, the Drawer clicks on the "Right" button to notify the Guesser and to end the game.

If the player selects Guesser, the window shows a drawing canvas as well as a text field into which the player can type his or her guess. The Guesser cannot draw on the canvas. Instead, the Drawer's drawing appears in this canvas. At any point, the Guesser can type a guess in the text field. When the Guesser hits the return/enter key, the guess is sent to the Drawer and appears on the Drawer's screen.

Since this is a networked program, we do not provide a demo online. Below are shapshots of a game in progress. The first display shows the Drawer's window. The Drawer is attempting to draw "graduation."

The next display shows the Guesser's window. The Guesser thinks that the drawing looks like a woman with a nest on her head.

Organization

Our implementation comprises four classes:

  1. Pictionary, which is a WindowController.

  2. Cards, which handles the reading of the cards from file.

  3. Guesser, which represents the guesser in the game.

  4. Drawer, which represents the drawer in the game.

We have completely implemented the Pictionary and Guesser classes, and most of Cards and Drawer. We have placed comments in the Cards and Drawer classes indicating where you should add code and what that code should do.

How to Run the Program

Once your program has been written, you will begin by running two versions of the program by just selecting "run" twice. When both versions are open, move the top-most window so that you can see both windows. You will need to make one of these the Drawer and the other the Guesser. Since the Drawer is the server, you must start the Drawer first. You can do this by selecting the "Drawer" button in one of the windows. (If you mistakenly start the Guesser first, the System console will display the error message "Could not connect to server".) The Drawer will ask you to find the "cards.txt" file. It can be found inside your starter directory. Now select the "Guesser" button on the other window. You are now ready to play. The game ends when the Drawer clicks the "Right" button.

The Code

The Cards class
Begin by filling in the details of the Cards class. We have implemented everything except the part of the constructor which reads the card information from the cardFile and loads each line into an element of the cards array. We have provided a BufferedReader for you to use. You should read each successive line from this BufferedReader into a new element of the array cards.

You will be done when you either run out of stuff to read (readLine() returns null) or you've filled the array. When you are done, the variable numCards must contain the total number of cards. Make sure this is accurate as it will be used by shuffle. [Yes, we know, we don't really need to shuffle since we only ever pull one card from the deck. We just wanted you to see how it could be done!]
The Drawer class
The Drawer acts as a server in a client/server relationship. Its constructor sets up a ServerSocket, drawingServer, and then waits to accept a connection from the client. Once this has happened, the Drawer will create an input stream, guessStream, and an output stream, out, in order to communicate with the Guesser. The writeLine method should send along the output stream the Line segments that should be drawn on the Guesser's canvas. (The writeLine method is called from the onMouseDrag method of Pictionary.java.) From the input stream it will accept guesses.

We have implemented everything but the run() and writeLine methods. The writeLine method's only job is to write its Line parameter to the network output stream so that Guesser can pick it up and write it to its canvas. If anything goes wrong, just call the close() method to close up all open streams.

Because the Lines being sent to the Guesser are Objects, it is appropriate to send them through the ObjectOutputStream, out, created in the constructor. Unlike the examples in class, you should not use a BufferedOutputStream because we want the Lines to appear as soon as they are produced, not being passed a handful at a time as a BufferedOutputStream would do.

Guesses are Strings. We made guessStream a BufferedReader, as that will handle Strings appropriately.

Getting Started

Read through the Card and Drawer classes, noting the lines that ask you to add code. Those are the only places where you will need to make changes to the files. You may also find it useful to refer to the networked Drawing Panel example from class and also look at the Guesser class to see exactly what it is expecting to receive and send on its end of the streams.

The starter code is set up to allow both the Drawer and Guesser to be on the same computer. While it is beyond the requirements of the assignment, you might enjoy actually getting them to play on different computers. To do that, go into the Guesser class and change the Socket constructor call. Replace "localhost" with the Internet (IP) address of another machine.

To find the name of another computer in the lab, go to that machine and click on the apple icon at the top left of the screen. Click on "About this Mac", then "More Info ...". On the left of the window that appears, click on "Network". Look at the of the window in the line labelled "Built-in Ethernet" and write down the number in the last column, which should look something like "134.173.66.240". This number should replace "localhost" in your code. Be sure to place quotation marks around the number so it is treated as a string. For example, on this computer, I would replace "localhost" by "134.173.66.240".

Please be sure, however, that the code you turn in uses "localhost". If you pass a string that is not a valid computer name, when you start the Guesser, you will get the message "Unknown host". Remember that the Drawer must start first since it is the server.

Grading Point Allocations

Value

Feature
Syntax Style (4 pts total)
1 pt. Descriptive comments
1 pt. Good names
1 pt. Good use of constants
1 pt. Appropriate formatting
Semantic style (3 pts total)
1 pt. conditionals and loops
1 pt. General correctness/design/efficiency issues
1 pts. Parameters, variables, and scoping
Correctness (3 pts total)
1 pt. sending Lines
1 pt. receiving guesses
1/2 pt. reading in data to cards array
1/2 pt. closing up socket and streams

Submitting Your Work

Your program is due on Monday at 11 p.m. When your work is complete, follow the same procedure for submitting as usual. Make sure the folder name begins with your name(s) and includes the phrase "Lab12." Also make sure that the Drawer.java and Card.java files include a comment containing your name(s).

Before turning in your work, be sure to double check both its logical organization and your style of presentation. Make your code as clear as possible and include appropriate comments.