CS202 -- Lab 2 (Spring 2024)
Inspiration
Connect Four (http://en.wikipedia.org/wiki/Connect_Four) is a simple game
where two players take turns placing colored discs into a seven-column,
six-row grid. Today, we will implement a simple version of Connect Four
using composition.
This is a reworking of a popular lab of mine at my prior institution focused
on developing simple classes, in a straightforward OOP style, to a simple
game. Like all of our early labs this will also give you more experience
with C++ and some of its powerful features.
Rubric
This lab is more difficult to test using scripts so the TAs will develop
a framework they think is best and a draft rubric is posted below as of last 202/302 go-round.
Part 1: Column class
- First, we will develop a class called C4Col, which will be
responsible for simply storing discs placed into columns. C4Col
should contain three private data members: an integer storing the
number of discs placed in the column (so far), an integer storing
the maximum number of discs allowed (i.e., # of rows = 6), and a simple
character array to store representations of each players' discs (more later).
Remember: initialization must be done in the constructor, not the .h file
- Develop an interface (i.e, prototypes of the member functions for this
class in your .h file) composed of a default constructor and the following
member functions: int isFull(), which determines if the column is full
(i.e., numDiscs == maxDiscs); char getDisc(int), which returns the requested
element of the private character array (i.e., getDisc(0) will return
Discs[0]); int getMaxDiscs(), which returns the maximum number of discs
(i.e., number of rows); and void addDisc(char), which adds the character
representing a disc to the next open slot in the Disc array (i.e.,
Discs[numDiscs++] = newDisc). Remember: developing an interface simply
means adding function prototypes inside a new class .h file as we have done
in lecture. Although there are hints on how to implement these, the
functions go in a separate .cpp file (see below).
- Implement a default constructor for the C4Col class in your
implementation file (.cpp). This default constructor will initialize
the current and maximum number of discs to 0 and 6, respectively, and
initialize the character array with ' ' characters.
REMINDER 1: constructors have no type; C4Col::C4Col(){} is an empty constructor. All member functions should have a type, e.g., int getDisc(int)
REMINDER 2: discs[ i ] = " "; is a compiler error... it must be ' ' in C++.
- Implement the member functions listed (and hinted at in the corresponding
video) in your emerging .cpp file. If addDisc is called and the column is full, display a message but do nothing else. If the parameter given to getDisc is invalid, also display an error message to the user and do nothing.
(hint: you should use isFull() in addDisc() for maximum code reusability)
Part 2: Developing a board class
- The second class will represent a Connect 4 board and contain data
members that are C4Col objects. This concept is called composition.
- Develop the C4Board class starting with an interface (.h) that
includes two private data members: an integer for the number of columns
and an array of C4Col objects to represent the Connect 4 board (e.g. C4Col
Board[100]; the constructor you developed in part 1 will be automatically
run for all elements of this array). Next, add prototypes in your interface
for a default constructor and two public member functions: void display(),
which will display the current board in simple text; and void play(), which
will allow two players to play a game. REMINDER: you will need to also
include the header developed in part 1 here to declare C4Cols like this:
#include "C4Col.h"
- Implement the member functions for this C4Board class. The default
constructor should set the number of columns to be the row size of a
Connect 4 board (n = 7). As mentioned above, constructors for the composed
class (C4Col) are run automatically. Display() could contain a nested for
loop that decreases from numRows - 1 to 0 in the outside loop and from 0 to
numCols - 1 on the inside as:
for (int i = board[0].getMaxDiscs() - 1; i >= 0; i--) {
...
for (int j = 0; j < numCols; j++)
cout << board[j].getDisc(i) << " ";
...
}
NOTE: You must include "C4Col.h" and "C4Board.h" in this new .cpp file
- Add extra formatting to the above to make the board look proper including
a separator character (e.g., '|') between columns, a number
indicating which column
is which for playing the game, and other enhancement (use your creativity
here). Play() should display the current board (using display to maximize
code reuse) and ask one of two players which column they would like to add
their disc, or -1 to end the game. Use an 'X' character for player 1 discs
and an 'O' character for player 2 discs (HINT: like tic-tac-tow,
(turn % 2)+ 1 will give you
the appropriate player if player 1 always goes first). Use addDisc from the
C4Col class to complete the turn.
- Your main function/client program should be very simple. Declare a
C4Board object (as we need at least one instantiated to use member
functions), and then call its play member function at a minimum like
this:
/* insert comments here */
#include "C4Board.h" // class definition for C4Board used below
int main() {
C4Board c4; // instantiate an instance of a C4Board object
c4.play(); // play game!!
}
Part 3: Finishing up
- Finish your Connect4 game by adding a private member function (called
a helper function in the text) that can determine if a player has won and,
if they have, displays a congratulatory message. If you have trouble, please
see the instructor or the TAs. HINT: This is similar to the 2-D array
manipulation you did for Lab 1 (tic-tac-toe), but A[i][j] becomes
A[i].getDisc(j) using composition.
- Kick it up a notch (5% extra credit): Develop a computer player that
follows your move with a move of its own. Feel free to make this simple
(choose a random non-full column) or as sophisticated of an AI as you'd like.
Testing your code prior to submission
To faciliate testing, you were previously asked to clone the course Github repository as follows:
git clone https://github.com/semrich/CS202-24.git cs202
For this assignment, update this clone by using the following:
git pull
We'll discuss this in class but note that your client must be named
"main.cpp" and compilable using make. Unlike other assignments this
term, you will get more credit for the structure of your
code and following instructions versus solving unit tests. Please refer
to the final rubric for details.
Rubric
We will grade your submission relative to the rubric below.
Part 1: 21 points
+4 Basic program structure is correct
- program commented well (2 pts)
- proper .h and .cpp files for C4Col and C4Board (2 pts)
+3 default constructor works as requested
+10 member functions are correct (2 pt each)
- isFull()
- getDisc()
- getMaxDiscs()
- addDisc()
+4 Invalid inputs checked in addDisc and getDisc (2 pts each).
Part 2/3: 19 points
+2 default constructor for Board works as intended
+4 Board is displayed correctly.
+3 plays game correctly with 'X' and 'O characters for player 1 and 2, respectively.
+2 Checks for legal/illegal moves correctly.
- you will only be expected to check invalid integer input; we will not put chars or strings in the game for testing
+8 Correctly determines when game is over.
Extra credit: Any computer player, no matter how simple, will receive 10% extra
points relative to Parts 1 - 3. For example, a score of 35/40 would receive 1.75 extra credit points, making the score ~37/40.
The eight specific test cases are as follows:
0 1 0 1 0 1 0
4 5 4 5 4 5 4
6 5 5 4 4 3 4 3 2 3 3
0 1 1 2 3 2 2 3 4 3 3
0 0 1 1 2 2 3
6 6 5 5 4 4 3
3 4 4 5 5 6 5 6 2 6 6
0 0 0 0 1 1 6 1 2 2 5 3
If you wish to have you program 'play' without having to type everything
in 1 by 1, we will use (from your shell) e.g.
printf '0 1 0 1 0 1 0' | ./main
Submission
Like the prior lab, you must create a single .tar for this assignment.
The command to do so is:
tar -cvf lab2.tar C4Col.h C4Col.cpp C4Board.h C4Board.cpp main.cpp
Because this assignment is more focused on C++ syntax/class design vs.
solving specific problems, and since we checked for a very similar win
condition in Lab 1, most of rubric above is on specific
syntax/code items vs. solving scripts in advance.
Note: Although submission will be faciliated by Canvas, we will compile and test on EECS lab
machines!
If you develop your solution elsewhere please make sure it works on
the lab computers prior to the deadline.