Previous review of this project:
Deck and Card classes and member-accessing with one header
I'm nearly finished with my deck of cards project, and this time I made changes to hide the Card
class by nesting it in the Deck
class. I'm still getting correct results when displaying the deck. However, I do now realize that I can no longer maintain Card
objects outside the class. Instead, I have to call Card deal()
with a Deck
object in order to retrieve a Card
, and I cannot store that Card
anywhere.
Does this render my design ineffective for this purpose? If so, how else can I maintain Card
s outside the class while still preventing the user from directly constructing a Card
? Would a private
constructor (with Card
un-nested from Deck
) be a better option?
Deck.h
#ifndef DECK_H
#define DECK_H
#include <iostream>
#include <array>
class Deck
{
private:
class Card
{
private:
char rank;
char suit;
unsigned value;
public:
Card::Card() : value(0), rank(' '), suit(' ') {}
Card::Card(char r, char s, unsigned v) : rank(r), suit(s), value(v) {}
bool operator<(const Card &rhs) const {return (value < rhs.value);}
bool operator>(const Card &rhs) const {return (value > rhs.value);}
bool operator==(const Card &rhs) const {return (suit == rhs.suit);}
bool operator!=(const Card &rhs) const {return (suit != rhs.suit);}
friend std::ostream& operator<<(std::ostream &out, const Card &aCard);
friend std::ostream& operator<<(std::ostream &out, const Card &aCard)
{return out << '[' << aCard.rank << aCard.suit << ']';}
};
static const unsigned VALUES[13];
static const char RANKS[13];
static const char SUITS[4];
static const unsigned MAX_SIZE = 52;
std::array<Card, MAX_SIZE> cards;
int topCardPos;
public:
Deck();
void shuffle();
Card deal();
unsigned size() const {return topCardPos+1;}
bool empty() const {return topCardPos == -1;}
friend std::ostream& operator<<(std::ostream &out, const Deck &aDeck);
};
#endif
Deck.cpp
#include <algorithm>
#include "Deck.h"
const unsigned Deck::VALUES[13] = {1,2,3,4,5,6,7,8,9,10,10,10,10};
const char Deck::RANKS[13] = {'A','2','3','4','5','6','7','8','9','T','J','Q','K'};
const char Deck::SUITS[4] = {'H','D','C','S'};
Deck::Deck() : topCardPos(-1)
{
for (unsigned rank = 0, value = 0; rank, value < 13; ++rank, ++value)
{
for (unsigned suit = 0; suit < 4; ++suit)
{
topCardPos++;
cards[topCardPos] = Card(RANKS[rank], SUITS[suit], VALUES[value]);
}
}
shuffle();
}
void Deck::shuffle()
{
topCardPos = MAX_SIZE-1;
std::random_shuffle(&cards.front(), &cards.back()+1);
}
Deck::Card Deck::deal()
{
if (empty())
{
std::cerr << "\nDECK IS EMPTY\n";
Card blankCard;
return blankCard;
}
topCardPos--;
return cards[topCardPos+1];
}
std::ostream& operator<<(std::ostream &out, const Deck &aDeck)
{
for (unsigned iter = aDeck.size(); iter--> 0;)
{
out << "\n" << aDeck.cards[iter];
}
return out;
}