Executive Summary

For this project you will implement the client part of a networked version of the "Tic Tac Four" game pictured here. I've already implemented the server, so if you can get a client up and running it will allow players on different machines to play against one another. For the regular project you will develop a terminal client - which will require object-oriented programming skills as well as some programming with threads and some programming with sockets.

Honor

The course policy and the instructions it references, most pertinently COMPSCIDEPTINST 1531.1C, spell out what kinds of assistance are permissable for programming projects. The instructor can give explicit permission for things that would otherwise not be allowed. For this project, you have explicit permission
  1. to get help from both Spring 2015 IC211 instructors (any assistance must be documented though), and
  2. to use general purpose Java resources online (though such use must be documented). Resources that might specifically address this project, like the code of programs that play tic-tac-toe, are not allowed.
Put together the instructions referenced in the course policy and the explicit permissions above, and what you get is summarized as:

The TicTacTwo Protocol

You can either connect to the TicTacTwo server I have running on mich302csd01u.academy.usna.edu using port 30111, or you can run a server locally by downloading TicTacTwoServer.jar
curl -O http://www.usna.edu/Users/cs/wcbrown/courses/S15IC211/proj/p03/TicTacTwoServer.jar
and running it on the host of your choice like this:
java -jar TicTacTwoServer.jar
The protocol the server "speaks" is described in detail below. First, here are some basic conventions about the game and how gameplay is described.
  1. The board is a 5x5 grid. When the game starts none of the X's and O's are on the board, and the grid is positioned in the center of the board.
  2. Board coordinates are row,col format, starting at one (not zero), so row=1, col=1 is the upper left position on the board
  3. The pieces are X1,X2,X3,X4; O1,O2,O3,O4; and G (the grid)
  4. The coordinate associated with the grid is the coordinate of its center. So putting the grid at row=3, col=3 means placing it in the center of the board.
  5. The X-player has first move.
  6. All commands sent to the server should be terminated by a newline.

Here is the precise description of the protocol used to communicate with the server. Note that extra text comprising an "extra-message" can be added on to the end of any of these messages - in either direction. None-the-less, all messages (even with their "extra" part) are single-line messages.

sender message description commentary
client request-game playername opponentrequest

server responses
error 11 username taken
error 13 timeout
error 15 unimplemented feature
new-game X-playername O-playername
In request-game, the first argument playername is the name of the player making the request. The second argument, opponentrequest, can be the name of the desired opponent or any, which indicates the user will play any available player. The value ai is reserved for future use - currently no ai player is implemented.

The first name listed in the new-game response is the X-player, and thus the player with the first move.

client move piece row col

server responses
error 21 not your turn
error 23 invalid move
ok
Valid values for piece are X1,X2,X3,X4,O1,O2,O3,O4,G.

If the server response is ok, then the opposing player is notified of the move (see server's move message below).

server error 1 invalid command Any line set to the server that is not recognized as a valid command will result in this response.
server move piece row col
This message notifies a player of a successful move by the opposing player.
server game-over res
This message notifies the player that the game is over. A res value of 1 means that this player has won. A res value of 0 means that this player has lost. The server will close the socket connecting it to this player on its end after receiving this message.

Step 0 [up to 0 pts]: be the client

Pair up with someone, and play a game (or at least part of one) using netcat to connect to the server, and thus participate as a client in the protocol. Suppose john and paul want to play
what john doeswhat paul does
~/$ nc mich302csd01u.academy.usna.edu 30111
request-game john paul
~/$ nc mich302csd01u.academy.usna.edu 30111
request-game paul john

The goal: A terminal client

The goal of the project is to write a client for the game that runs in the terminal. If you do a good job of this, most of the code you produce would be able to be reused were you to make a GUI client. Your terminal client will run as follows
  *   *   *   *   * 

  *   X | X | *   O 
     -----------
  *   * | O | *   * 
     -----------
  *   X | * | *   * 

  *   *   *   *   O
  1. It will be run as
    • java P3Client1 playername opponentrequest
      in which case the server defaults to mich302csd01u.academy.usna.edu and the port defaults to 30111.
    • java P3Client1 playername opponentrequest servername
      in which case the port defaults to 30111.
    • java P3Client1 playername opponentrequest servername port
      in which case the user specifies everything
  2. It will display in the board in ASCII art form, as displayed to the right or in the Ugly non-ASCII Art Form described below, that gets updated with each successful move by either player.
  3. The user has four commands:
    • place row col — which places the "next" piece (X's if you're the X-player, O's if you're the O player) that it not currently on the board at position row,col
    • move row1 col1 row2 col2 — which moves the piece at position row1 col1 to position row2 col2.
    • deprecated!
      x place-grid row col
      move-grid dir — where dir can be up, down left, right.
    • quit - which quits the game (just close the socket).

Step 1A [up to 25(20) pts]: make a board class (25 for ASCII Art, 20 for non-ASCII Art)

A nice OOP way to attack this is to first make a class for representing boards. That means the 5x5 grid, the four X pieces and the four O pieces (which are initially off the board), and the grid (which is initally in the center of the board). Make a nice main to test this that simply loops forever printing out the board, and reading in a "move" message in the TicTacTwo Protocol format (move piece row col) updating the board. You needn't do any error checking, you can assume no bad moves are made, and you can let a ctrl-c end the program.

NEW! I'm OK with you printing out the Simple non-ASCII Art Version of the board for this part rather than the Beautiful ASCII Art Version. It's more important to ensure you have the board represented and then to move on to the networking portion, Step 1B.

Ugly non-ASCII Art Version Beautiful ASCII Art Version
~/$ java Board
> move X1 3 3
G 3 3
X1 3 3
X2 NB	      
X3 NB	      
X4 NB	      
O1 NB	      
O2 NB	      
O3 NB	      
O4 NB	      

> move O1 2 4
G 3 3
X1 3 3
X2 NB	      
X3 NB	      
X4 NB	      
O1 2 4	      
O2 NB	      
O3 NB	      
O4 NB	      


> move G 3 4
G 3 4
X1 3 3
X2 NB	      
X3 NB	      
X4 NB	      
O1 2 4	      
O2 NB	      
O3 NB	      
O4 NB	      
~/$ java Board
> move X1 3 3

  *   *   *   *   * 

  *   * | * | *   * 
     -----------
  *   * | X | *   * 
     -----------
  *   * | * | *   * 

  *   *   *   *   * 

> move O1 2 4
  *   *   *   *   * 

  *   * | * | O   * 
     -----------
  *   * | X | *   * 
     -----------
  *   * | * | *   * 

  *   *   *   *   * 

> move G 3 4
  *   *   *   *   * 
                    
  *   *   * | O | * 
         -----------
  *   *   X | * | * 
         -----------
  *   *   * | * | * 

  *   *   *   *   * 

Step 1B [up to 55(50) pts]: A single-threaded partial client using TicTacTwo Protocol syntax

Most of the interaction between client and server is turn-based: you read user input, translate it into the protocol and send that message to the server, then you read a single line of server response and update things according to the respons. Then you do it all over again. This can be done by a single-threaded program. What can't you do this way? You can't handle the "win" message easily, and you can't handle the user's quit message, since your program may be sitting there waiting to read the server's message informing you of your opponent's move. In this step, write a client that connects to the server, displays the board, and from the server, handles everything but the win message and from the user, handles only "move" commands given in the TicTacTwo Protocol format. That means the user is not yet using the nice user input language, but rather the uglier TicTacTwo Protocol language. (Note: Look at the basic client sockets code from the previous lesson as a starting place.) The program should be run as follows:

The following is a sample run of this program. Note that the uses the pretty ASCII Art output, but it's fine if you use the ugly non-ASCII Art output.

~/$ java P3Client1 MrMeow any 
You are O

  *   *   *   *   * 

  *   * | * | *   * 
     -----------
  *   * | * | *   * 
     -----------
  *   * | * | *   * 

  *   *   *   *   * 
Opponent: move X1 3 3
continuing ...


  *   *   *   *   * 

  *   * | * | *   * 
     -----------
  *   * | X | *   * 
     -----------
  *   * | * | *   * 

  *   *   *   *   * 
> move O1 2 2

  *   *   *   *   * 

  *   O | * | *   * 
     -----------
  *   * | X | *   * 
     -----------
  *   * | * | *   * 

  *   *   *   *   * 
Opponent: move X2 4 4     
continuing ...


  *   *   *   *   * 

  *   O | * | *   * 
     -----------
  *   * | X | *   * 
     -----------
  *   * | * | X   * 

  *   *   *   *   * 
> move G 2 3

  *   * | * | *   * 
     -----------
  *   O | * | *   * 
     -----------
  *   * | X | *   * 

  *   *   *   X   * 

  *   *   *   *   * 
Opponent: move X3 3 4     
continuing ...


  *   * | * | *   * 
     -----------
  *   O | * | *   * 
     -----------
  *   * | X | X   * 

  *   *   *   X   * 

  *   *   *   *   * 
> move O2 3 2

  *   * | * | *   * 
     -----------
  *   O | * | *   * 
     -----------
  *   O | X | X   * 

  *   *   *   X   * 

  *   *   *   *   * 
and so on ...

Miscellaneous requirements and suggestions:

Step 1C [up to 85(80) pts]: A single-threaded partial client supporting the user commands - place, move, move-grid (but not quit)

This version of the client basically does the same thing that the previous version did, except the player now gives the "user command syntax" rather than "TicTacTwo Protocol syntax".

~/$ java P3Client1 MrMeow any 
You are O

  *   *   *   *   * 

  *   * | * | *   * 
     -----------
  *   * | * | *   * 
     -----------
  *   * | * | *   * 

  *   *   *   *   * 
Opponent: move X1 3 3
continuing ...


  *   *   *   *   * 

  *   * | * | *   * 
     -----------
  *   * | X | *   * 
     -----------
  *   * | * | *   * 

  *   *   *   *   * 
> place 2 2

  *   *   *   *   * 

  *   O | * | *   * 
     -----------
  *   * | X | *   * 
     -----------
  *   * | * | *   * 

  *   *   *   *   * 
Opponent: move X2 4 4     
continuing ...


  *   *   *   *   * 

  *   O | * | *   * 
     -----------
  *   * | X | *   * 
     -----------
  *   * | * | X   * 

  *   *   *   *   * 
> move-grid up

  *   * | * | *   * 
     -----------
  *   O | * | *   * 
     -----------
  *   * | X | *   * 

  *   *   *   X   * 

  *   *   *   *   * 
Opponent: move X3 3 4     
continuing ...


  *   * | * | *   * 
     -----------
  *   O | * | *   * 
     -----------
  *   * | X | X   * 

  *   *   *   X   * 

  *   *   *   *   * 
> move 2 2 3 2

  *   * | * | *   * 
     -----------
  *   * | * | *   * 
     -----------
  *   O | X | X   * 

  *   *   *   X   * 

  *   *   *   *   * 
and so on ...

Miscellaneous requirements and suggestions:

Step 1D [up to 100(95) pts]: A multi-threaded client

This version of the program handles the win server-message properly (displays the message "Game over, you lose!" or "Game over, you win!" as appropriate), and handles the "quit" command properly (the client to which the command was given should display "Quitting game!" and exit, the other client should dispaly "Game ended unexpectedly! Perhaps your cowardly opponent quit." and exit).

~/$ java P3Client1 bar any     
You are O
Opponent: move X1 3 3

  *   *   *   *   * 

  *   * | * | *   * 
     -----------
  *   * | X | *   * 
     -----------
  *   * | * | *   * 

  *   *   *   *   * 
continuing ...

> place 2 2

  *   *   *   *   * 

  *   O | * | *   * 
     -----------
  *   * | X | *   * 
     -----------
  *   * | * | *   * 

  *   *   *   *   * 
Opponent: move X2 4 4     

  *   *   *   *   * 

  *   O | * | *   * 
     -----------
  *   * | X | *   * 
     -----------
  *   * | * | X   * 

  *   *   *   *   * 
continuing ...

>  move-grid up

  *   * | * | *   * 
     -----------
  *   O | * | *   * 
     -----------
  *   * | X | *   * 

  *   *   *   X   * 

  *   *   *   *   * 
Opponent: move X3 1 3     

  *   * | X | *   * 
     -----------
  *   O | * | *   * 
     -----------
  *   * | X | *   * 

  *   *   *   X   * 

  *   *   *   *   * 
continuing ...

> move 2 2 2 4

  *   * | X | *   * 
     -----------
  *   * | * | O   * 
     -----------
  *   * | X | *   * 

  *   *   *   X   * 

  *   *   *   *   * 
Opponent: move X4 2 3     

  *   * | X | *   * 
     -----------
  *   * | X | O   * 
     -----------
  *   * | X | *   * 

  *   *   *   X   * 

  *   *   *   *   * 
> Game over, you lose!

To deal properly with the "win" message and and the user's "quit" command, you really need two threads: one that reads user commands from standard in, and the other that reads server responses and messages from the socket. I'm not going to tell you how to write your code, but I do have a suggestion: I would make a Queue of "moves". Whenever the user-input-reading thread reads a command from the user and writes a move message to the socket, enqueue that move. You don't know if it's an OK move yet, so don't change the board. Whenever the socket-reading thread reads an "ok" from the server, you dequeue the move and make it happen to your board. Whenever you read an error message response from the server, you dequeue the move and throw it away - there was something wrong with it. If the user says "quit", the user-input-reading thread should close the socket and exit the program. If the socket-reading-thread reads a "win" message, or if the socket is shut down from the server side (which you'll notice because the Scanner you made from the InputStream returns false for "hasNext()"), print the appropriate message as described above, and exit the program.

When to submit

Project 3 is due by COB on Wednesday, April 29th, according to the course's particular definition of "COB". Late projects incurr a penalty of 3N points, where N is the number of days late. So, a project that is not turned in by COB Wednesday, but which is turned in by COB Thursday receives a 3 point penalty. A project that is not turned in by COB Thursday, but which is turned in by COB Friday receives a 9 point penalty. And so on.

What to submit

Your electronic submission must include:
  1. all .java file required to compile and run your program - including the ones you were given in the assignment
  2. a file named README with your name and alpha code, which step you are submitting for (including any extra credit), and any issues you know your program has.
Your paper submission must inlcude:
  1. A completed copy of this coversheet on paper.
  2. A printout of your README file plus all of your .java files all done as a single codeprint-generated file! Please make sure that your name and alpha code appear in evey single file .java file.

How to submit

The paper portions of your submission should be stapled together and slid under your prof's door. For electronic submission, continue to use the same method from the previous projects. Within the directory on your Virtual Machine where you have been saving your project, type:
ic211-submit proj03 files-to-include
Where files-to-include is a list of all the files you're supposed to submit. Submitting more than you need to submit is always OK. Just be sure that all the files needed to compile and run your project are there. So, assuming you have a directory for this project and that you are in that directory, you could submit like this:
ic211-submit proj03 README *.java *.txt
You may submit files at any time, but only the last submission will be used for grading.

How projects are graded / how to maximize your points

Things to keep in mind to receive full marks:
  1. Submit all required items (as described above) on time.
  2. Do not submit any .java files that do not compile! Whichever Step you submit, your project should compile and run correctly at that step. If it doesn't, you should be submitting the previous step.
  3. Make sure your output matches the example output in all ways.
  4. Use good object-oriented design! The means adhering to the principles of ecapsulation, data/information hiding, inheritance and polymorphism.
  5. Practice good Java Style. This means proper indentation, use of whitespace within lines of code, logical organization of chunks of code, proper naming of classes, methods, fields and constants in accordance with Java conventions. This means good commenting: your name & alpha in every file, and descriptive comments for each public method at a minimum!
Most important: Look at the the grading sheet!