CS140 -- Lab 3 (Spring 2021)
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 we'll post a corresponding rubric
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/CS140-21.git cs140
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.
Submission
Having done a trial run on Lab 0/Challenge 1, and on Lab 1 (see Tom's
comments on Piazza) we think it would be easiest for everyone to create a
single .tar for this assignment. The command to do so is:
tar -cvf lab3.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 the to-be posted rubric will be 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.