C++ Practice Assignment #4 - Blackjack in C++

Implementing blackjack in C++ can be a big task. Since the game involves players, a deck of cards and the house, we have to break down the code into smaller parts. This is where we use the power of C++’s object orientated abilities to implement classes. Firstly we need get a visual diagram of how we are sorting the code and an overview of the game. Without this, we would get confused and lose track of what’s going where.

overview of blackjack

Now Lets have a look at how exactly we are implementing blackjack in C++ with the help of organising the code into header and implementation files. Remember that with C++, we can share data from other header files by importing in the file.

blackjack

Card header file

</pre>
<pre>/*
=========================================================
Blackjack in C++
Made with Visual Studio 2010
File:card.h
=========================================================
*/

/*
====================================
Defining header
====================================
*/

#ifndef CARD_H
#define CARD_H

/*
=======================================
Included files
=======================================
*/
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <ctime>

using namespace std;

/*
=================================================
Card Class
=================================================
*/ 
class Card
{
public:
enum rank {ACE = 1, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN,
JACK, QUEEN, KING};

enum suit {CLUBS, DIAMONDS, HEARTS, SPADES};

friend ostream&amp; operator &lt;&lt; (ostream&amp; os, const Card&amp; aCard);

Card(rank r = ACE, suit s = SPADES, bool ifu = true);

/*
================================
Returns the value of a card
================================
*/
int GetValue() const;

/*
============================================================
Flips a card; if face up, becomes face down and vice versa
============================================================
*/
void Flip();

private:
rank m_Rank;
suit m_Suit;
bool m_IsFaceUp;
};

#endif
</pre>
<pre>

Card implementation file

</pre>
<pre>/*
=========================================================
Blackjack in C++
Made By Sahil Bora
Made with Visual Studio 2010
File:card.cpp
=========================================================
*/

#include "card.h"

/*
==================================================
Card Constructor
==================================================
*/

Card::Card(rank r, suit s, bool ifu): m_Rank(r), m_Suit(s), m_IsFaceUp(ifu)
{}

/*
=========================================
Get the value of the card
=========================================
*/

int Card::GetValue() const
{
/*
==========================================
If a card is face down, its value is 0
==========================================
*/
int value = 0;
if (m_IsFaceUp)
{
/*
========================================
Value is number showing on card
========================================
*/
value = m_Rank;

/*
=======================================
Value is 10 for face cards
=======================================
*/
if (value &gt;10)
value = 10;
}
return value;
}

/*
==================================================
Flip the card 
==================================================
*/
void Card::Flip()
{
m_IsFaceUp = !(m_IsFaceUp);
}</pre>
<pre>

Deck header file

</pre>
<pre>/*
=========================================================
Blackjack in C++
Made with Visual Studio 2010
File:deck.h
=========================================================
*/

/*
======================================
Defining header
======================================
*/
#ifndef DECK_H
#define DECK_H

/*
==========================================
Included files
==========================================
*/
#include "hand.h"
#include "genericPlayerClass.h"

/*
=============================================
Deck Class
=============================================
*/
class Deck : public Hand
{
public: 
Deck();

virtual ~Deck();

/*
=========================================
Create a standard deck of 52 cards
=========================================
*/
void Populate();

/*
==============================
Shuffle cards
==============================
*/
void Shuffle();

/*
===================================
Deal one card to a hand
===================================
*/
void Deal(Hand&amp; aHand);

/*
=============================================
Give additional cards to a generic player
=============================================
*/
void AdditionalCards(GenericPlayer&amp; aGenericPlayer);
};

#endif</pre>
<pre>

Deck implementation file

</pre>
<pre>/*
=========================================================
Blackjack in C++
Made By Sahil Bora
Made with Visual Studio 2010
File:deck.cpp
=========================================================
*/

/*
================================
Included files
================================
*/
#include "deck.h"

/*
===================================
Reserve 52 cards
===================================
*/
Deck::Deck()
{
m_Cards.reserve(52);
Populate();
}

/*
===============================
Deck deconstructor
===============================
*/
Deck::~Deck()
{}

/*
=======================================
Populate the cards
=======================================
*/
void Deck::Populate()
{
Clear();
/*
===================================
Create standard deck
===================================
*/
for (int s = Card::CLUBS; s &lt;= Card::SPADES; ++s)
for (int r = Card::ACE; r &lt;= Card::KING; ++r)
Add (new Card(static_cast&lt;Card::rank&gt;(r),
static_cast&lt;Card::suit&gt;(s)));
}

/*
====================================
Randomize and Shuffle the cards
====================================
*/
void Deck::Shuffle()
{
random_shuffle(m_Cards.begin(), m_Cards.end());
}

void Deck::Deal(Hand&amp; aHand)
{
if (!m_Cards.empty())
{
aHand.Add(m_Cards.back());
m_Cards.pop_back();
}
else
{
cout &lt;&lt; "Out of cards. Unable to deal";
}
}

/*
===============================================
Additional cards 
===============================================
*/

void Deck::AdditionalCards(GenericPlayer&amp; aGenericPlayer)
{
cout &lt;&lt; endl;

/*
===================================================================
continue to deal a card as long as generic player isn't busted 
and wants another hit
===================================================================
*/
while (!(aGenericPlayer.IsBusted()) &amp;&amp; aGenericPlayer.IsHitting())
{
Deal(aGenericPlayer);
cout &lt;&lt; aGenericPlayer &lt;&lt; endl;

if (aGenericPlayer.IsBusted())
aGenericPlayer.Bust();
}
}</pre>
<pre>

Game header file

</pre>
<pre>/*
=========================================================
Blackjack in C++
Made By Sahil Bora
File:game.h
=========================================================
*/

/*
=====================================
Defining header
=====================================
*/
#ifndef GAME_H
#define GAME_H

/*
=============================================
Included files
=============================================
*/
#include "deck.h"
#include "house.h"
#include "player.h"

/*
==============================================
Game Class
==============================================
*/
class Game
{
public:
Game(const vector&lt;string&gt;&amp; names);

~Game();

/*
==================================
Plays the game of blackjack
==================================
*/
void Play();

private:
Deck m_Deck;
House m_House;
vector&lt;Player&gt; m_Players;
};

#endif</pre>
<pre>

Game implementation file

</pre>
<pre>/*
=========================================================
Blackjack in C++
Made with Visual Studio 2010
File:game.cpp
=========================================================
*/

/*
======================================
Included files
======================================
*/
#include "game.h"
#include "player.h"
#include "card.h"

/*
=========================================
Game constructor
=========================================
*/
Game::Game(const vector&lt;string&gt;&amp; names)
{
/*
=======================================================
Create a vector of players from a vector of names
=======================================================
*/
vector&lt;string&gt;::const_iterator pName;

for (pName = names.begin(); pName != names.end(); ++pName)
m_Players.push_back(Player(*pName));

/*
=====================================
The random number generator
=====================================
*/

srand(time(0)); 
m_Deck.Populate();
m_Deck.Shuffle();
}

/*
========================================
Game desconstructor
========================================
*/
Game::~Game()
{}

/*
===============================================
Play the game
===============================================
*/
void Game::Play()
{
/*
===========================================
Deal initial 2 cards to everyone 
===========================================
*/
vector&lt;Player&gt;::iterator pPlayer;
for (int i = 0; i &lt; 2; ++i)
{
for (pPlayer = m_Players.begin(); pPlayer != m_Players.end(); 
++pPlayer)
m_Deck.Deal(*pPlayer);
m_Deck.Deal(m_House);
}

/*
==================================
Hide house's first card
==================================
*/
m_House.FlipFirstCard();

/*
=======================================
Display everyone's hand
=======================================
*/
for (pPlayer = m_Players.begin(); pPlayer != m_Players.end(); ++pPlayer)
cout &lt;&lt; *pPlayer &lt;&lt; endl;
cout &lt;&lt; m_House &lt;&lt; endl;

/*
==========================================
Deal additional cards to players
==========================================
*/
for (pPlayer = m_Players.begin(); pPlayer != m_Players.end(); ++pPlayer)
m_Deck.AdditionalCards(*pPlayer);

/*
====================================
Reveal house's first card
====================================
*/
m_House.FlipFirstCard();
cout &lt;&lt; endl &lt;&lt; m_House;

/*
========================================
Deal additional cards to house
========================================
*/
m_Deck.AdditionalCards(m_House);

if (m_House.IsBusted())
{
/*
====================================
Everyone still playing wins
====================================
*/
for (pPlayer = m_Players.begin(); pPlayer != m_Players.end();
++pPlayer)
if (!(pPlayer−&gt;IsBusted()))
pPlayer−&gt;Win();
}

else
{
/*
==============================================
Compare each player still playing to house
==============================================
*/
for (pPlayer = m_Players.begin(); pPlayer != m_Players.end();
++pPlayer)
if(!(pPlayer−&gt;IsBusted()))
{
if(pPlayer−&gt;GetTotal() &gt; m_House.GetTotal())
pPlayer−&gt;Win();
else if (pPlayer−&gt;GetTotal() &lt; m_House.GetTotal())
pPlayer−&gt;Lose();
else
pPlayer−&gt;Push();
}
}

/*
==========================================
Remove everyone's cards
==========================================
*/
for (pPlayer = m_Players.begin(); pPlayer != m_Players.end(); ++pPlayer)
pPlayer−&gt;Clear();
m_House.Clear();
}
</pre>
<pre>

Generic player header file

</pre>
<pre>/*
=========================================================
Blackjack in C++
Made By Sahil Bora
Made with Visual Studio 2010
File:genericPlayerClass.h
=========================================================
*/

/*
==================================
Defining header
==================================
*/

#ifndef GENERICPLAYERCLASS_H
#define GENERICPLAYERCLASS_H

/*
=======================================
Included files
=======================================
*/

#include "card.h"
#include "hand.h"

/*
=================================================
Generic Player class
=================================================
*/
class GenericPlayer : public Hand
{
friend ostream&amp; operator &lt;&lt; (ostream&amp; os, 
const GenericPlayer&amp; aGenericPlayer);

public:
GenericPlayer(const string&amp; name = "");

virtual ~GenericPlayer();

/*
=================================================================
Indicates wheater or not generic player wants to keep hitting
=================================================================
*/
virtual bool IsHitting() const = 0;

/*
=========================================================================
returns wheater generic player has busted − has a total greater than 21
=========================================================================
*/
bool IsBusted() const;

/*
============================================
Annouces that the generic player bust
============================================
*/
void Bust() const;

protected:
string m_Name;
};

#endif 
</pre>
<pre>

Generic Player Class Implementation file

</pre>
<pre>/*
=========================================================
Blackjack in C++
Made with Visual Studio 2010
File:genericPlayerClass.cpp
=========================================================
*/

/*
======================================
Included files
======================================
*/
#include "genericPlayerClass.h"

/*
=====================================================
Name constructor 
=====================================================
*/
GenericPlayer::GenericPlayer(const string&amp; name): m_Name(name)
{}

/*
======================================
Generic player
======================================
*/
GenericPlayer::~GenericPlayer()
{}

/*
================================================
If the player has over 21 and is busted
================================================
*/

bool GenericPlayer::IsBusted() const
{
return (GetTotal() &gt; 21);
}

/*
=============================================
Say that the player is busted
=============================================
*/

void GenericPlayer::Bust() const
{
cout &lt;&lt; m_Name &lt;&lt; "busted.\n";
}</pre>
<pre>

Hand header file

</pre>
<pre>/*
=========================================================
Blackjack in C++
Made with Visual Studio 2010
File:hand.h
=========================================================
*/

/*
=========================================
Defining header
=========================================
*/
#ifndef HAND_H
#define HAND_H

/*
===============================================
Included files
===============================================
*/
#include "card.h"

/*
=================================================
Hand Class
=================================================
*/ 
class Hand
{
public:
Hand();

virtual ~Hand();

/*
==============================================
Adds a card to the hand
==============================================
*/

void Add(Card* pCard);

/*
===============================================
Clears hand of all cards
===============================================
*/
void Clear();

/*
==============================================================
Gets hand total value, intelligently treats aces as 1 or 11
==============================================================
*/

int GetTotal() const;

protected:
vector&lt;Card*&gt; m_Cards;
};

#endif
</pre>
<pre>

Hand implementation file

</pre>
<pre>/*
=========================================================
Blackjack in C++
Made with Visual Studio 2010
File:hand.cpp
=========================================================
*/

/*
====================================
Included files
====================================
*/
#include "hand.h"

/*
==============================================
Reserve 7 cards 
==============================================
*/
Hand::Hand()
{
m_Cards.reserve(7);
}

/*
=================================================
Virtual deconstructor of Hand
=================================================
*/
Hand::~Hand() 
{
Clear();
}

/*
====================================================
Add a card 
====================================================
*/
void Hand::Add(Card* pCard)
{
m_Cards.push_back(pCard);
}

/*
================================================
Clear the cards
================================================
*/

void Hand::Clear()
{
/*
=========================================================
Iterate through vector, freezing all memory on the heap
=========================================================
*/
vector&lt;Card*&gt;::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();
}

/*
===========================================
Get total of cards in the hand
===========================================
*/
int Hand::GetTotal() const
{
/*
==============================================
If no cards in hand, return 0
==============================================
*/
if(m_Cards.empty())
return 0;

/*
====================================================================
If a first can has value of 0, then card is face down; return 0
====================================================================
*/
if(m_Cards[0]−&gt;GetValue() == 0)
return 0;

/*
=====================================================
Add up card values, treat each ace as 1
=====================================================
*/
int total = 0;
vector&lt;Card*&gt;::const_iterator iter;

for(iter = m_Cards.begin(); iter != m_Cards.end(); ++iter)
total += (*iter)−&gt;GetValue();

/*
=========================================
Determine if hand contains an ace
=========================================
*/
bool containsAce = false;
for (iter = m_Cards.begin(); iter != m_Cards.end(); ++iter)
if ((*iter)−&gt;GetValue() == Card::ACE)
containsAce = true;

/*
=================================================================
If hand contains ace and total is low enough, treat ace as 11
=================================================================
*/
if(containsAce &amp;&amp; total &lt;= 11)
/*
=======================================================
Add only 10 since we've already added 1 for the ace
=======================================================
*/
total +=10;

return total;
}
</pre>
<pre>

House header file

</pre>
<pre>/*
=========================================================
Blackjack in C++
Made with Visual Studio 2010
File:house.h
=========================================================
*/

/*
==========================================
Defining header
==========================================
*/

#ifndef HOUSE_H
#define HOUSE_H

/*
===========================================
Included files
===========================================
*/

#include "genericPlayerClass.h"

/*
=============================================
House Class
=============================================
*/

class House : public GenericPlayer
{
public:
House(const string&amp; name = "House");

virtual ~House();

/*
====================================================================
Indicates wheater house is hitting (will always hit on 16 or less
====================================================================
*/
virtual bool IsHitting() const;

/*
======================================
Flips over first card
======================================
*/
void FlipFirstCard();
};

#endif</pre>
<pre>

House implementation file

</pre>
<pre>/*
=========================================================
Blackjack in C++
Made with Visual Studio 2010
File:house.cpp
=========================================================
*/

/*
=====================================
Included files
=====================================
*/

#include "house.h"

/*
==================================================
Generic Player game
==================================================
*/

House::House(const string&amp; name): GenericPlayer(name)
{}

/*
==========================================
House deconstructor
==========================================
*/
House::~House()
{}

/*
===========================================
If the player is hitting
===========================================
*/
bool House::IsHitting() const
{
return (GetTotal() &lt;= 16);
}

/*
======================================
Flip the first card
======================================
*/

void House::FlipFirstCard()
{
if(!(m_Cards.empty()))
m_Cards[0]−&gt;Flip();
else
cout &lt;&lt; "No card to flip!\n";
}
</pre>
<pre>

Player header

</pre>
<pre>/*
=========================================================
Blackjack in C++
Made with Visual Studio 2010
File:player.h
=========================================================
*/

/*
=======================================
Defining header
=======================================
*/
#ifndef PLAYER_H
#define PLAYER_H

/*
=========================================
Included files
=========================================
*/
#include "genericPlayerClass.h"

/*
==============================================
Player Class
==============================================
*/
class Player : public GenericPlayer
{
public:
Player(const string&amp; name = "");

virtual ~Player();

/*
=========================================================
Returns wheater or not the player wants another hit
=========================================================
*/
virtual bool IsHitting() const;

/*
=============================================
Announces that the player wins
=============================================
*/
void Win() const;

/*
=============================================
Announces that the player loses
=============================================
*/
void Lose() const;

/*
=============================================
Announces that the player pushes
=============================================
*/
void Push() const;
};

#endif</pre>
<pre>

Player implementation file

</pre>
<pre>/*
=========================================================
Blackjack in C++
Made By Sahil Bora
Made with Visual Studio 2010
File:card.cpp
=========================================================
*/

/*
========================================
Included files
========================================
*/

#include "player.h"

/*
==========================================
Player Generic Player constructor
==========================================
*/
Player::Player(const string& name): GenericPlayer(name)
{}

/*
==================================
Player deconstructor
==================================
*/
Player::~Player()
{}

/*
==============================================
If player wants to hit a card
==============================================
*/
bool Player::IsHitting() const
{
cout << m_Name << ", do you want a hit (Y/N): ";
char response;
cin >> response;

return (response == 'y' || response == 'Y');

}

/*
======================================
If the player wins
======================================
*/
void Player::Win() const
{
cout << m_Name << " wins.\n";
}

/*
========================================
If the player has lost
========================================
*/

void Player::Lose() const
{
cout << m_Name << " loses.\n";
}

/*
======================================
If the player continues
======================================
*/
void Player::Push() const
{
cout << m_Name << " pushes.\n";
}
</pre>
<pre>

Putting it all together in the “main.cpp” file

</pre>
<pre>/*
=========================================================
Blackjack in C++
Made By Sahil Bora
Made with Visual Studio 2010
File:main.cpp
=========================================================
*/

#include "card.h"
#include "deck.h"
#include "game.h"
#include "genericPlayerClass.h"
#include "hand.h"
#include "house.h"
#include "player.h"

/*
=======================================
Fuction prototypes
=======================================
*/
ostream&amp; operator &lt;&lt; (ostream&amp; os, const Card&amp; aCard);
ostream&amp; operator &lt;&lt; (ostream&amp; os, const GenericPlayer&amp; aGenericPlayer);

int main()
{
cout &lt;&lt; "\t\tWELCOME TO BLACKJACK!\n\n";

int numPlayers = 0;
while (numPlayers &lt; 1 || numPlayers &gt; 7)
{
cout &lt;&lt; "How many Players? (1−7): ";
cin &gt;&gt; numPlayers;
}

vector&lt;string&gt; names;
string name;
for (int i = 0; i &lt; numPlayers; ++i)
{
cout &lt;&lt; "Enter player name: ";
cin &gt;&gt; name;
names.push_back(name);
}
cout &lt;&lt; endl;

/*
================================
The Game Loop
================================
*/
Game aGame(names);
char again = 'y';
while (again != 'n' &amp;&amp; again != 'N')
{
aGame.Play();
cout &lt;&lt; "\nDo you want to play again? (Y/N): ";
cin &gt;&gt; again;
}

return 0;
}

/*
============================================================
Overloads &lt;&lt; operator so Card object can be sent to cout
============================================================
*/
ostream&amp; operator &lt;&lt;(ostream&amp; os, const Card&amp; aCard)
{
const string RANKS[] = {"0", "A", "2", "3", "4", "5", "6", "7", "8", "9",
"10", "J", "Q", "K"};
const string SUITS[] = {"c", "d", "h", "s"};

if (aCard.m_IsFaceUp)
os &lt;&lt; RANKS[aCard.m_Rank] &lt;&lt; SUITS[aCard.m_Suit];
else
os &lt;&lt; "XX";

return os;
}

/*
======================================================================
Overloads &lt;&lt; operator so a Generic Playe object can be sent to cout
======================================================================
*/
ostream&amp; operator&lt;&lt;(ostream&amp; os, const GenericPlayer&amp; aGenericPlayer)
{
os &lt;&lt; aGenericPlayer.m_Name &lt;&lt; ":\t";

vector&lt;Card*&gt;::const_iterator pCard;
if (!aGenericPlayer.m_Cards.empty())
{
for (pCard = aGenericPlayer.m_Cards.begin();
pCard != aGenericPlayer.m_Cards.end(); ++pCard)
os &lt;&lt; *(*pCard) &lt;&lt; "\t";
if (aGenericPlayer.GetTotal() != 0)
cout &lt;&lt; "(" &lt;&lt; aGenericPlayer.GetTotal() &lt;&lt; ")";
}
else
{
os &lt;&lt; "&lt;empty";
}

return os;
}</pre>
<pre>
Share this post