Project 4 — Board Game Collection

Assigned Tuesday, April 15th
Program Due Friday, April 25th by 11:59pm
Weight 10%
Updates
  • The "Sample Session" section now has real examples.
  • The "How to Start" section gives a hint about how to temporarily configure Reversi to use a smaller board to test the endgame.
  • Slightly modified versions of the files Proj4.cpp and Proj4Aux.cpp have been put up; the only changes are that main() now calls game->OutputGreeting() at the beginning, and DoOnePlayer() now prints a newline after getting user input, making the output from running the program with redirected input nicer. Please download the new versions.

Objectives

To gain experience:

  1. Designing a hierarchy of classes related classes
  2. Redefining methods in child classes
  3. Using pointers
  4. Using dynamic memory and pointers
  5. Writing constructors and destructors

Project Policy

This project is considered an CLOSED project. Please review the open project policy before beginning your project.

Overview: the Grid Game Collection Program

You will be developing a game suite program that will grow to implement what you hope will be a large collection of grid-based board games. You are planning to use C++'s class hierarchy and inheritance mechanisms to minimize redundant coding and maximize software reuse. You want to eventually become the Candy Crush of the barely-interactive gaming genre. Many internet companies have started on more idiotic premises, so who knows?

You are planning to start your company in stealth mode by implementing Phase 1 of your plan as your Project 4 submission for CMSC 202. The professor secretly supports your plan and has provided a bunch of code for you. However, as in Project 3, he got distracted by a shiny object and has only done a partial design and implementation. He has finished a full set of specifications, though, and will provide that, and a good grade on your project, in return for your completing the design and implementation, and giving him a 51% equity stake in your startup.

Description

A grid-based board game is one that is played on an orthogonal grid; some examples are checkers, Reversi, Battleship, Risk, and good old-fashioned tic-tac-toe. Your modest goal for Project 4 is to build a program that will play just two of these grid-based board games: Reversi and tic-tac-toe. You want to do it in a way that reflects good OOP principles.

The professor started your class hierarchy for you. He initially laid out a skeleton for three C++ classes:

He then moved on to writing the driver code in the files Proj4.cpp, Proj4Aux.cpp, and Proj4Aux.h. He did a complete job on these files: they compiled and ran correctly, and are in their final form. You should not have to touch these; in fact, changing them is prohibited (see "Requirements" below).

As the professor was writing the driver code, however, he also substantially redesigned the game classes, to reflect a cleaner, more OOP design. However, he accidentally deleted the latest versions of these game classes! He was able to retrieve older versions from backup, and since it's at least useful as something to build from, he decided to provide those to you. You will have to modify them substantially.

Implementation

You will have to do the following three steps to build a working Project 4:

Step 1: Abstract out common code from child classes and move it to the parent

The Reversi implementation was the first class the professor worked on, and he wasn't thinking much about the TicTacToe class, or their parent GridGame class. So, he put a lot of the code into the Reversi class at first. Then, as he worked on the driver code, he realized much of the Reversi functionality could be made more general and moved into the parent GridGame class with very little effort. That way, it could be inherited and reused by the TicTacToe class, as well as other game classes in the future.

Note that the code in Proj4.cpp and Proj4Aux.cpp were written based upon the new game class hierarchy design, so there are enough hints there to tell you exactly which member functions were migrated up from Reversi to GridGame, and which were left in Reversi.

When you do migrate the functions, you must make sure that they will now ework for both Reversi and TicTacToe objects! Remember that by parametrizing code, you can make a lot of it shared: for example, while Reversi has an 8x8 board and tic-tac-toe is 3x3, if you feed in the dimension as a parameter, the process of printing out the board for the two different games is actually identical.

STEP 2: Implement the TicTacToe class

Now, you should work on the TicTacToe class. There were several functions that were too game-specific to be put into the GridGame class: functions like making an actual move, determining when the game was over, and printing the end-of-game statistics are all very game-specific.

The Reversi class has full implementations for these functions, which you can use for inspiration. You should name your functions in the TicTacToe class with the exact same names So,, for example your TicTacToe class must have a function TicTacToe::DoMove() to match the equivalent function in the Reversi class, but with entirely different logic.

STEP 3: Compile, Test, Repeat

Since Proj4.cpp and Proj4Aux.cpp were written to the new class design, but the game classes we provided are the old design, there will be lots of compiler errors. You will go through a few more compile/revise/recompile cycles on ths project than past ones.

The Grid Game main()

The main() function is provided for you, and has a specific execution syntax: it takes one runtime argument, either the string "ttt" or "reversi", to indicate which game you want to play. It will then construct an object of the proper game type, and go into a loop requesting moves from the user (always a row and column, just like in Project 1's Reversi). It firsts validates the move by asking the game object, then if it is judged a good move, it will actually play the move. Before each turn of the loop, it will ask the game object if the game is over yet. When the game is done, main() asks the object to print out end-of-game statistics, and then exits.

Requirements

1. You may not change any of the code in Proj4.cpp, Proj4Aux.h, or Proj4Aux.cpp. You should not even submit these files. You are free to change and of the rest of the files, and add any additional files.

2. You many not use the keyword virtual in this project. I.e., no virtual functions are allowed. For those of you who already know what these are and are peeved that we're not letting you use them: we are imposing this restriction because it is important for you to know what C++ does when only static binding is utilized. If you don't know what the last sentence even meant, all the better.

3. If you use any dynamic objects as members in your classes, you must have appropriate destructors for the class that deletes these dynamic objects. You can use the one in GridGame as an example.

Hints

We mentioned above that you can make a set of slightly different functions common, by using parameters to customize the function to the various subclasses' needs. The thing is, the user of the various game classes (main() in this case) will probably not know what that parameter should be, nor should it properly need to. So, main() should not have to call "game->OutputBoard(boardSize)"; it should be able to just say "game->OutputBoard()"... which is what it in fact does. So how can you get the necessary "parameter" into the OutputBoard() function? Can you say "data member"? We leave it up to you to figure out the details.

Provided Code

Going along with the progression of the projects in this course, we are providing even less overt design guidance on this project than previously. Instead of documentation specifications that you must write code to match, you must now actually analyze existing code for hints on how your class must work.

First, there are the provided working driver source files; these files must not be modified:

Next, there are the starter templates for the game classes, which you must significantly modify and augment:

(The state of these files was described in the sections above.)

If you've ssh’ed into the GL servers, you can copy all of the files over directly: issue the following command at the command prompt while you’re inside your project directory:

cp /afs/umbc.edu/users/p/a/park/pub/cmsc202/spring14/proj4/* .
(Note the '.' at the end of the command--that is very important.)

Additionally, you are free to add any helper functions to make your program more modular and cleaner in design, although we don't see the need for any.

Example Session

The program takes one command line argument: either "ttt" or "reversi" to select which game to launch. It then goes into a contiuous loop, reading in a row and column to play the next piece on, making sure it's a valid move, then executing the move. It then prints out the resulting state of the game board. It automatically detects when the game is done, and prints out the final results.

The following is a sample run:

$ ./Proj4.out
Syntax: ./Proj4.out {ttt|reversi}
$ ./Proj4.out ttt
Welcome to TicTacToe!

Player X's move: 1 1

X--
---
---

Player O's move: 1 3

X-O
---
---

Player X's move: 2 1

X-O
X--
---

Player O's move: 2 3

X-O
X-O
---

Player X's move: 3 1

X-O
X-O
X--
Player X wins!
$ ./Proj4.out ttt
Welcome to TicTacToe!

Player X's move: 1 1

X--
---
---

Player O's move: 0 0

Illegal move: Row or column out of range

Player O's move: 1 1

Illegal move: Position already played

Player O's move: 1 2

XO-
---
---

Player X's move: 2 1

XO-
X--
---

Player O's move: 3 1

XO-
X--
O--

Player X's move: 2 3

XO-
X-X
O--

Player O's move: 2 2

XO-
XOX
O--

Player X's move: 3 2

XO-
XOX
OX-

Player O's move: 3 3

XO-
XOX
OXO

Player X's move: 1 3

XOX
XOX
OXO
The game is a tie
$ ./Proj4.out reversi
Welcome to Reversi!

Player X's move: 1 1

X-------
--------
--------
--------
--------
--------
--------
--------

Player O's move: 2 2

X-------
-O------
--------
--------
--------
--------
--------
--------

Player X's move: 3 3

X-------
-X------
--X-----
--------
--------
--------
--------
--------

Player O's move: 

The Reversi game keeps going on, with output very much like Project 1. You just have to leave the logic of the provided code as-is to guarantee correct operation and output.

How to Test Your Project

At this point, you should know pretty well how to test your program. Since more of your algorithmic coding will be in the TicTacToe class, make sure that works well. You should throughly test your program for all typical, edge, and error cases.

Note that since the Reversi game in this project does not let the user choose a board size, it will always play with a full 8x8 board, which will make it tedious for you to test the endgame. You can temporarily edit the constant REVERSI_BOARD_SIZE down to a small number like 4 to test that out. However, make sure you remember to set it back to 8 before sumitting your code!

Additional Requirements

As always, you will have to create a Makefile.

Grading

See the course website for a description of how your project will be graded.

We will be automating much of the grading for this project. It is absolutely essential that you do not modify any of the files that we provided to you that we instruct you not to alter; You should not even submit these files. If you do inadvertantly submit your copies of these files, we will be replacing them with our own versions before trying to compile and run your program.

Another requirement is that your executable, as produced by your Makefile, is called Proj4.out; adjust your Makefile accordingly.

Project Submission

Before submitting your project, be sure to compile and test your code on the GL system. See the Project Compilation section of the course Projects page for details on how to compile and execute your project on GL.

Assuming you’ve used the specified file names, submit your project by typing the command

submit cs202 proj4 [all of your various .h and .cpp files] Makefile

See the Project Submission page for detailed instructions. Note that we require you to submit the Makefile, also. We will in fact be using your own Makefile to build your program, so it must work properly.

You may resubmit your files as often as you like, but only the last submittal will be graded and will be used to determine if your project is late. Also note that if you rename or remove certain files, the old versions that you submitted earlier will stay in the submit directory unless you use "submitrm" to clean them out, which you should. At the end, a "submitls" should show exactly those files that are part of your project: no more, no less. For more information, see the Projects page on the course web site.

Remember — if you make any change to your program, no matter how insignificant it may seem, you should recompile and retest your program before submitting it. Even the smallest typo can cause errors and a reduction in your grade.