Skip to main content

How To Think Like a Computer Scientist C++ Edition The Pretext Interactive Version

Section 12.2 Card objects

If you are not familiar with common playing cards, now would be a good time to get a deck, or else this chapter might not make much sense. There are 52 cards in a deck, each of which belongs to one of four suits and one of 13 ranks. The suits are Spades, Hearts, Diamonds and Clubs (in descending order in Bridge). The ranks are Ace, 2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen and King. Depending on what game you are playing, the rank of the Ace may be higher than King or lower than 2.
If we want to define a new object to represent a playing card, it is pretty obvious what the instance variables should be: rank and suit. It is not as obvious what type the instance variables should be. One possibility is strings, containing things like "Spade" for suits and "Queen" for ranks. One problem with this implementation is that it would not be easy to compare cards to see which had higher rank or suit.
An alternative is to use integers to encode the ranks and suits. By “encode,” I do not mean what some people think, which is to encrypt, or translate into a secret code. What a computer scientist means by “encode” is something like “define a mapping between a sequence of numbers and the things I want to represent.” For example,
Table 12.2.1. Mapping suits to integers
Spades 3
Hearts 2
Diamonds 1
Clubs 0
The symbol is mathematical notation for “maps to.” The obvious feature of this mapping is that the suits map to integers in order, so we can compare suits by comparing integers. The mapping for ranks is fairly obvious; each of the numerical ranks maps to the corresponding integer, and for face cards:
Table 12.2.2. Mapping ranks to integers
Jack 11
Queen 12
King 13
The reason I am using mathematical notation for these mappings is that they are not part of the C++ program. They are part of the program design, but they never appear explicitly in the code. The class definition for the Card type looks like this:
struct Card {
  int suit, rank;

  Card();
  Card(int s, int r);
};

Card::Card() {
  suit = 0;  rank = 0;
}

Card::Card(int s, int r) {
  suit = s;  rank = r;
}
There are two constructors for Cards. You can tell that they are constructors because they have no return type and their name is the same as the name of the structure. The first constructor takes no arguments and initializes the instance variables to a useless value (the zero of clubs).
The second constructor is more useful. It takes two parameters, the suit and rank of the card.
The following code creates an object named threeOfClubs that represents the 3 of Clubs:
Card threeOfClubs(0, 3);
The first argument, 0 represents the suit Clubs, the second, naturally, represents the rank 3.

Checkpoint 12.2.1.

Checkpoint 12.2.2.

What does it mean to encode the ranks and suits?
  • To translate each rank / suit into a secret code.
  • Incorrect! This is called encryption.
  • To create strings to represent each rank / suit.
  • Incorrect! We create strings before we encode.
  • To define a mapping between each rank / suit and a sequence of numbers.
  • Correct! This makes it easier to compare cards.
  • To write code describing real objects, like cards, with their respective ranks / suits.
  • Incorrect! This is how we describe object-oriented programming.

Checkpoint 12.2.3.

Checkpoint 12.2.4.

What is the purpose of mapping?
  • To have better organization in your code.
  • Incorrect! Mapping helps more with order than with organization.
  • To make it possible to compare objects that have non-numerical values.
  • Correct! By mapping non-numerical values to integers, we can compare them!
  • To represent complex objects visually.
  • Incorrect! There is nothing visual about mapping.
  • To add complexity to your code.
  • Incorrect! Mapping actually simplifies your code.
You have attempted 1 of 4 activities on this page.