Previous Exercise | Next Exercise | Lecture | Top Level

Cards

Context

Using the same technique as in the last exercise, we will add another monopoly object to our game: the event cards.

Let's analyse them. First of all, there doesn't seem to be a fundamental difference between the chance cards and the community chest cards. We will therefore represent both types by the same class.

We will again put all the cards into one big CardIndex and use a CardPtr to refer to the data in the index. Similar to the DeedPtrList, we will use a CardPtrDeque which will behave like a stack of cards: we can draw the topmost card and put back a card underneath the bottom of the stack.

The card event will be implemented in the execute() member function of every card object. In this change, we will just have a function stub for this member function, as we do not yet have enough objects to effectively implement the execute() member function. What we can do is further classify the types of cards we have. I did this classification for you:

JailCard
Get out of jail for free.
GotoJailCard
Go to jail, do not pass go.
RepairCard
Pay x per house and y per hotel.
PayCard
Pay x to bank (negative values allowed).
PayAllCard
Pay x to all players (negative values allowed)
AdvanceCard
Go to nearest type of space.
AdvanceToCard
Go to space.
AdvanceByCard
Advance by x steps (negative values allowed). Observe the entity relationship diagram:

erd

Exercises

Change 17
Unlike change 12, we can immediatly implement the Card class and it's subclasses. Since the subclasses are going to be so small and similar (use cut&paste!), we will all put them into one pair of header/implementation files with the basename CardTypes.

The file Card.h is provided, you have to write CardTypes.h and CardTypes.C. Note that the Card class contains no data and has only one pure virtual function. Therefore, it doesn't need an implementation file Card.C!

Use the Key class to store destinations. We will replace this with the appropriate class once we defined it. As usual, looking at the tests can provide helpful hints

Change 18
Implement the CardIndex class and add a data member called cards to the Game class. This change is almost identical to change 12. No header file will be provided, you have to write it. As usual, looking at the tests can provide helpful hints.

Change 19
Implement the CardPtr and the CardPtrDeque classes. Both classes will share the same header file CardPtr.h. Note how we overload the assignment operator=() to pop off a card from the deque or to slip it back underneath. As usual, looking at the tests can provide helpful hints.

Change 20
We are beginning to have a sizeable amount of game data. To facilitate testing, we will add a file game.data to our source files. As we add more and more monopoly objects, this file will eventually contain the whole game database.

You will note that the file contains two CardPtrDeque entries, one for the community chest stack, one for the chance stack. Add data members called chest and chance to the Game class so that it can read and write the game.data file.

Warning! There is a catch: CardPtrDeque uses CardPtr, which in turn uses Game in it's definition. Therefore, you cannot simply declare an element of type CardPtrDeque in Game since this would result in a circular definition. Instead, you can make a forward declaration of CardPtrDeque and use a pointer to it in the declaration of Game in Game.h. You can initialize this pointer to the real thing inside the constructor in Game.C. Don't forget to delete your items in the destructor.

Yet another reason to use the strict separation between definition and implementation...


Christian Goetze