Subscribe to MentalFloss Minutes        RSS Feed
-----

Deck of Cards

Icon Leave Comment
Been seeing a few posts on here about building a deck of cards, so I figured I'd work it out in C++.

#include <iostream>

using namespace std;

enum Suit { HEARTS, CLUBS, DIAMONDS, SPADES };
enum Rank { ACE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING };
const string SUIT[] = { "♥", "♣", "♦", "♠" };
const string RANK[] = { "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K" };

struct Card
{
	Suit suit;
	Rank rank;
};

class Deck
{
	private:
	Card cards[52];
		
	public:
	Deck()
	{
		new_pack();
	}
	
	void new_pack()
	{
		int card = 0;
		for(int suit = HEARTS; suit <= SPADES; suit++)
		{
			for(int rank = ACE; rank <= KING; rank++)
			{
				cards[card].suit = (Suit)suit;
				cards[card].rank = (Rank)rank;
				card++;
			}	
		}
	}
	
	void test_print()
	{
		int card = 0;
		for(int suit = HEARTS; suit <= SPADES; suit++)
		{
			for(int rank = ACE; rank <= KING; rank++)
			{
				Card current = cards[card];
				cout << RANK[current.rank] << SUIT[current.suit] << "  ";
				card++;
			}
			cout << endl;
		}
	}
};

int main()
{
	Deck deck;
	deck.test_print();
	return 0;
}



A♥  2♥  3♥  4♥  5♥  6♥  7♥  8♥  9♥  10♥  J♥  Q♥  K♥  
A♣  2♣  3♣  4♣  5♣  6♣  7♣  8♣  9♣  10♣  J♣  Q♣  K♣  
A♦  2♦  3♦  4♦  5♦  6♦  7♦  8♦  9♦  10♦  J♦  Q♦  K♦  
A♠  2♠  3♠  4♠  5♠  6♠  7♠  8♠  9♠  10♠  J♠  Q♠  K♠  



Next, we want to shuffle a deck.

#include <iostream>
#include <algorithm>

using namespace std;

enum Suit { HEARTS, CLUBS, DIAMONDS, SPADES };
enum Rank { ACE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING };
const string SUIT[] = { "♥", "♣", "♦", "♠" };
const string RANK[] = { "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K" };

struct Card
{
	Suit suit;
	Rank rank;
};

class Deck
{
	private:
	Card cards[52];
		
	public:
	Deck()
	{
		new_pack();
		shuffle_deck();
	}
	
	void new_pack()
	{
		int card = 0;
		for(int suit = HEARTS; suit <= SPADES; suit++)
		{
			for(int rank = ACE; rank <= KING; rank++)
			{
				cards[card].suit = (Suit)suit;
				cards[card].rank = (Rank)rank;
				card++;
			}	
		}
	}
	
	void shuffle_deck()
	{
		random_shuffle(begin(cards), end(cards));
	}
	
	void test_print()
	{
		int card = 0;
		for(int suit = HEARTS; suit <= SPADES; suit++)
		{
			for(int rank = ACE; rank <= KING; rank++)
			{
				Card current = cards[card];
				cout << RANK[current.rank] << SUIT[current.suit] << "\t";
				card++;
			}
			cout << endl;
		}
	}
};

int main()
{
	Deck deck;
	deck.test_print();
	return 0;
}



5♥	K♠	Q♥	3♣	Q♣	10♦	5♣	J♦	A♦	Q♠	8♦	A♠	7♣
3♥	9♠	J♠	K♣	6♣	7♦	2♠	6♥	9♣	8♥	K♥	2♣	4♠
2♦	7♥	7♠	6♠	5♦	K♦	A♣	Q♦	4♥	4♣	4♦	5♠	10♥
10♣	9♥	J♣	8♣	9♦	2♥	J♥	6♦	A♥	8♠	3♠	10♠	3♦



If you're not required to implement it yourself, try to use what's available. In case you missed it, here's shuffle:

	void shuffle_deck()
	{
		random_shuffle(begin(cards), end(cards));
	}



So, we can create a new deck (simulated fresh pack of cards), shuffle the deck, and display the entire deck. From here, the complexity explodes. We want to be able to deal out these cards. There's a problem though. I used an array, which is locked at 52 cards. If we track an index through the array in our deals, and reach the end, we're supposed to shuffle the cards in dealt pile and reuse them. We can't just create a new deck because then there's too many cards out on the table.

The sanest option is to treat cards as actual cards, and in dealing them we remove them from the pile entirely. Instead of arrays, we want to use vectors.

Let's update the code.

#include <iostream>
#include <algorithm>
#include <vector>

#include <assert.h>

using namespace std;

enum Suit { HEARTS, CLUBS, DIAMONDS, SPADES };
enum Rank { ACE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING };
const string SUIT[] = { "♥", "♣", "♦", "♠" };
const string RANK[] = { "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K" };

struct Card
{
	Suit suit;
	Rank rank;
	
	Card(Suit suit, Rank rank)
	{
		this->suit = suit;
		this->rank = rank;
	}
};

class Deck
{
	private:
	vector<Card> cards;
		
	public:
	Deck()
	{
		new_pack();
		shuffle_deck();
	}
	
	void new_pack()
	{
		for(int suit = HEARTS; suit <= SPADES; suit++)
		{
			for(int rank = ACE; rank <= KING; rank++)
			{
				cards.push_back(Card((Suit)suit, (Rank)rank));
			}	
		}
		
		assert(cards.size() == 52);
	}
	
	void shuffle_deck()
	{
		random_shuffle(cards.begin(), cards.end());
	}
	
	void test_print()
	{	
		int card = 0;		
		for(int suit = HEARTS; suit <= SPADES; suit++)
		{
			for(int rank = ACE; rank <= KING; rank++)
			{
				Card current = cards[card];
				cout << RANK[current.rank] << SUIT[current.suit] << "\t";
				card++;
			}
			cout << endl;
		}
	}
};

int main()
{
	Deck deck;
	deck.test_print();
	return 0;
}



Now when we deal cards, we really deal them. They will be gone from the deck entirely, and can be returned back to the deck if that is demanded. We can choose an implementation here. If we want to deal from the back of the deck (internally, so who cares?) then we can stick with vector just fine. However, if we really want to be dealing from the front, we'll actually need to switch out vector for a deque (double ended queue) because vectors don't readily handle front insert/removal. Try both and see which you like. I'll stick with vector for this one though.

#include <iostream>
#include <algorithm>
#include <vector>

#include <assert.h>

using namespace std;

enum Suit { HEARTS, CLUBS, DIAMONDS, SPADES };
enum Rank { ACE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING };
const string SUIT[] = { "♥", "♣", "♦", "♠" };
const string RANK[] = { "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K" };

struct Card
{
	Suit suit;
	Rank rank;
	
	Card(Suit suit, Rank rank)
	{
		this->suit = suit;
		this->rank = rank;
	}
	
	string to_string()
	{
		return RANK[rank] + SUIT[suit];
	}
};

class Deck
{
	private:
	vector<Card> cards;
		
	public:
	Deck()
	{
		new_pack();
		shuffle_deck();
	}
	
	void new_pack()
	{
		for(int suit = HEARTS; suit <= SPADES; suit++)
		{
			for(int rank = ACE; rank <= KING; rank++)
			{
				cards.push_back(Card((Suit)suit, (Rank)rank));
			}	
		}
		
		assert(cards.size() == 52);
	}
	
	void shuffle_deck()
	{
		random_shuffle(cards.begin(), cards.end());
	}
	
	Card deal()
	{
		Card card = cards.back();
		cards.pop_back();
		return card;
	}
	
	void test_print()
	{	
		int card = 0;		
		for(int suit = HEARTS; suit <= SPADES; suit++)
		{
			for(int rank = ACE; rank <= KING; rank++)
			{
				Card current = cards[card];
				cout << RANK[current.rank] << SUIT[current.suit] << "\t";
				card++;
			}
			cout << endl;
		}
	}
};

int main()
{
	Deck deck;
	deck.test_print();
	cout << "==============================================" << endl;
	
	for(int i=0; i < 52; i++)
	{
		Card card = deck.deal();
		cout << "Dealer hands you: " << card.to_string() << endl;
	}
	return 0;
}



5♥	K♠	Q♥	3♣	Q♣	10♦	5♣	J♦	A♦	Q♠	8♦	A♠	7♣
3♥	9♠	J♠	K♣	6♣	7♦	2♠	6♥	9♣	8♥	K♥	2♣	4♠
2♦	7♥	7♠	6♠	5♦	K♦	A♣	Q♦	4♥	4♣	4♦	5♠	10♥
10♣	9♥	J♣	8♣	9♦	2♥	J♥	6♦	A♥	8♠	3♠	10♠	3♦
==============================================
Dealer hands you: 3♦
Dealer hands you: 10♠
Dealer hands you: 3♠
Dealer hands you: 8♠
Dealer hands you: A♥
Dealer hands you: 6♦
Dealer hands you: J♥
Dealer hands you: 2♥
Dealer hands you: 9♦
Dealer hands you: 8♣
Dealer hands you: J♣
Dealer hands you: 9♥
Dealer hands you: 10♣
Dealer hands you: 10♥
Dealer hands you: 5♠
Dealer hands you: 4♦
Dealer hands you: 4♣
Dealer hands you: 4♥
Dealer hands you: Q♦
Dealer hands you: A♣
Dealer hands you: K♦
Dealer hands you: 5♦
Dealer hands you: 6♠
Dealer hands you: 7♠
Dealer hands you: 7♥
Dealer hands you: 2♦
Dealer hands you: 4♠
Dealer hands you: 2♣
Dealer hands you: K♥
Dealer hands you: 8♥
Dealer hands you: 9♣
Dealer hands you: 6♥
Dealer hands you: 2♠
Dealer hands you: 7♦
Dealer hands you: 6♣
Dealer hands you: K♣
Dealer hands you: J♠
Dealer hands you: 9♠
Dealer hands you: 3♥
Dealer hands you: 7♣
Dealer hands you: A♠
Dealer hands you: 8♦
Dealer hands you: Q♠
Dealer hands you: A♦
Dealer hands you: J♦
Dealer hands you: 5♣
Dealer hands you: 10♦
Dealer hands you: Q♣
Dealer hands you: 3♣
Dealer hands you: Q♥
Dealer hands you: K♠
Dealer hands you: 5♥



At this point, there's a bunch of unknowns and loose ends and bugs, but we have a bit of a skeleton to work with, and should probably pick a game to implement. I want to think about it for a bit, so that's all for now.

0 Comments On This Entry

 

July 2019

S M T W T F S
 123456
78910111213
1415161718 19 20
21222324252627
28293031   

Tags

    Recent Entries

    Recent Comments

    Search My Blog

    2 user(s) viewing

    2 Guests
    0 member(s)
    0 anonymous member(s)