< Previous | Contents | Next >
I define the Hand class for a collection of cards.
class Hand
{
public:
Hand();
virtual ~Hand();
//adds a card to the hand void Add(Card* pCard);
//clears hand of all cards void Clear();
364 Chapter 10 n Inheritance and Polymorphism: Blackjack
//gets hand total value, intelligently treats aces as 1 or 11 int GetTotal() const;
protected:
vector<Card*> m_Cards;
};
Hand::Hand()
{
m_Cards.reserve(7);
}
Hand::~Hand()
{
Clear();
}
void Hand::Add(Card* pCard)
{
m_Cards.push_back(pCard);
}
void Hand::Clear()
{
//iterate through vector, freeing all memory on the heap vector<Card*>::iterator iter = m_Cards.begin();
for (iter = m_Cards.begin(); iter != m_Cards.end(); ++iter)
{
delete *iter;
*iter = 0;
}
//clear vector of pointers m_Cards.clear();
}
int Hand::GetTotal() const
{
//if no cards in hand, return 0 if (m_Cards.empty())
{
return 0;
Introducing the Blackjack Game 365
}
//if a first card has value of 0, then card is face down; return 0 if (m_Cards[0]->GetValue() = = 0)
{
return 0;
}
//add up card values, treat each ace as 1 int total = 0; vector<Card*>::const_iterator iter;
for (iter = m_Cards.begin(); iter != m_Cards.end(); ++iter)
{
total += (*iter)->GetValue();
}
//determine if hand contains an ace bool containsAce = false;
for (iter = m_Cards.begin(); iter != m_Cards.end(); ++iter)
{
if ((*iter)->GetValue() = = Card::ACE)
{
containsAce = true;
}
}
//if hand contains ace and total is low enough, treat ace as 11 if (containsAce && total <= 11)
{
//add only 10 since we’ve already added 1 for the ace total += 10;
}
return total;
}
Tra p
The destructor of the class is virtual, but notice that I don’t use the keyword virtual outside of the class when I actually define the destructor. You only use the keyword inside the class definition. Don’t worry; the destructor is still virtual.
366 Chapter 10 n Inheritance and Polymorphism: Blackjack
Although I’ve already covered this, I want to point it out again. All of the Card objects will exist on the heap. Any collection of cards, such as a Hand object, will have a vector of pointers to a group of those objects on the heap.
The Clear() member function has an important responsibly. It not only removes all of the pointers from the vector m_Cards, but it destroys the associated Card objects and frees the memory on the heap that they occupied. This is just like a real-world Blackjack game in which cards are discarded when a round is over. The virtual class destructor calls Clear().
The GetTotal() member function returns the point total of the hand. If a hand contains an ace, it counts it as a 1 or an 11, whichever is best for the player. The program accomplishes this by checking to see whether the hand has at least one ace. If it does, it checks to see whether treating the ace as 11 will put the hand’s point total over 21. If it won’t, then the ace is treated as an 11. Otherwise, it’s treated as a 1.