I have recently finished creating my own Deck
class for my Poker game. It works the way I want it to, but I would like to know if I can make it better and/or more efficient.
Deck.h
#ifndef DECK_H
#define DECK_H
#include "Card.h"
#include <iostream>
#include <string>
#include <ctime>
using namespace std;
class Deck
{
private:
static const string RANKS[13], SUITS[4];
int size;
Card cards[52];
void build();
public:
Deck();
~Deck();
void shuffle();
Card drawCard();
int getDeckSize() const {return size;}
friend ostream& operator<<(ostream&, const Deck&);
};
#endif
Deck.cpp
#include "Deck.h"
const string Deck::RANKS[13] = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
const string Deck::SUITS[4] = {"H","D","C","S"};
Deck::Deck() : size(0) {build();}
Deck::~Deck() {}
void Deck::build()
{
srand((unsigned int)time(NULL));
string card;
bool isSameCard;
while (size < 52)
{
isSameCard = false;
card = RANKS[rand()%13] + SUITS[rand()%4];
for (int i = 0; i < size; i++)
{
if (cards[i].getCard() == card)
{
isSameCard = true;
break;
}
}
if (!isSameCard)
{
cards[size].setCard(card);
size++;
}
}
}
void Deck::shuffle()
{
build();
srand((unsigned int)time(NULL));
for (int i = 0; i < size; i++)
{
int j = rand() % 52;
swap(cards[i], cards[j]);
}
}
Card Deck::drawCard()
{
if (size == 0)
{
cerr << "ERROR *** DECK EMPTY";
Card card;
return card;
}
size--;
return cards[size];
}
ostream& operator<<(ostream &out, const Deck &aDeck)
{
for (int i = aDeck.size-1; i >= 0; i--)
cout << *((aDeck.cards)+i) << endl;
return out;
}
Shuffling a Deck
object only requires a call to shuffle()
, so the object does not need to be destroyed for that. The shuffling algorithm works, and I tested this by making a separate check to make sure the deck never contains duplicates.
The driver for the class is in my Poker game itself, but I have tested each function sufficiently. I have both displayed the Deck
and its size, and have drawn some cards, a few times each run.
I'm paying particular attention to this class because I want to be able to reuse it for future programs. That is one of my biggest interests in this post.
====== REVISED ======
Deck.h
#ifndef DECK_H
#define DECK_H
#include "Card.h"
#include <ostream>
#include <string>
#include <vector>
using std::ostream;
using std::string;
using std::vector;
class Deck
{
private:
static const int MAX_SIZE = 52;
static const string RANKS[13];
static const string SUITS[4];
int size;
vector<Card> cards;
public:
Deck();
~Deck();
Card drawCard();
void shuffle();
int getDeckSize() const {return size;}
friend ostream& operator<<(ostream&, const Deck&);
};
#endif
Deck.cpp
#include "Deck.h"
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using std::ostream;
using std::vector;
const string Deck::RANKS[13] = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
const string Deck::SUITS[4] = {"H","D","C","S"};
Deck::Deck() : size(0)
{
for (int i = 0; i < 13; i++)
{
for (int j = 0; j < 4; j++)
{
Card t;
t.setCard(RANKS[i] + SUITS[j]);
cards.push_back(t);
size++;
}
}
shuffle();
}
Deck::~Deck() {}
void Deck::shuffle()
{
size = MAX_SIZE;
std::random_shuffle(&cards[0], &cards[MAX_SIZE-1]);
}
Card Deck::drawCard()
{
if (size == 0)
{
std::cerr << "ERROR *** DECK EMPTY";
Card card;
return card;
}
size--;
return cards[size];
}
ostream& operator<<(ostream &out, const Deck &aDeck)
{
for (int i = aDeck.size-1; i >= 0; i--)
out << aDeck.cards[i] << "\n";
return out;
}