Write a C++ program which has a main-driver and classes to make a 5-card poker-p
ID: 3891779 • Letter: W
Question
Write a C++ program which has a main-driver and classes to make a 5-card poker-playing game. I covered some of the basics for this in the class session on random number generation.
Make a PokerHand class with attribute:
int hand[5]; for storing the array of 5 cards
(using the integer encoding I showed in class)
and member functions:
hitMe(n) replaces the n-th card in hand[] with 1 card from deck[]
displayDeck() which displays the hand on the screen
and a Deck class which stores the whole deck as an array of int's
int deck[52] (using the integer encoding I showed in class)
and any / all constructors needed, including
member function shuffle which fills and randomizes the deck with 52 cards.
Your program must shuffle the deck and
provide a random hand.
Then loop asking for cards to replace, via hitMe( int k ) AND
each time through the loop, determine if you have (do at least 4 of the below tests)
Royal flush. A, K, Q, J, 10, all the same suit.
Straight flush. Five cards in a sequence, all in the same suit.
Four of a kind. All four cards of the same rank.
Full house. Three of a kind with a pair.
Flush. ...A flush is any 5 cards, all of the same suit.
Straight. ... Five cards of sequential value (numerical cards).
Three of a kind. ...
Two pair.
You may use a simple C++ sort routine (either from class or the Web).
Make sure the game is playable, as I will test playability.
Basically Loop, showing the hand, asking what to replace positionally, then determining
which of at least 4 evaluation conditions hold (like Flush, Straight, 3 of a kind, 2 pair)
or any 4 of the above conditions (as some are easier than others).
Explanation / Answer
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <ctime>
using namespace std;
// The 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};
// overloading << operator so can send Card object to standard output
friend ostream& operator << (ostream& os, const Card& aCard);
Card(rank r = ACE, suit s = SPADES, bool ifu = true);
// returns the value of a card, 1 - 11
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;
};
Card::Card(rank r, suit s, bool ifu): m_Rank(r), m_Suit(s), m_IsFaceUp(ifu)
{}
int Card::GetValue() const
{
// if a cards 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 > 10)
{
value = 10;
}
}
return value;
}
void Card::Flip()
{
m_IsFaceUp = !(m_IsFaceUp);
}
// The 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<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;
}
// if a first card has a value of 0, tgeb 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;
}
// The GenericPlayer Class
class GenericPlayer : public Hand
{
friend ostream& operator<<(ostream& os, const GenericPlayer& aGenericPlayer);
public:
GenericPlayer(const string& name = "");
virtual ~GenericPlayer();
protected:
string m_Name;
};
GenericPlayer::GenericPlayer(const string& name):
m_Name(name)
{}
GenericPlayer::~GenericPlayer()
{}
// The Player Class
class Player : public GenericPlayer
{
public:
Player(const string& name = "");
virtual ~Player();
// returns whether 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;
};
Player::Player(const string& name):
GenericPlayer(name)
{}
Player::~Player()
{}
bool Player::IsHitting() const
{
cout << m_Name << ", do you want a hit? (Y/N): ";
char response;
cin >> response;
return (response == 'y' || response == 'Y');
}
void Player::Win() const
{
cout << m_Name << " wins. ";
}
void Player::Lose() const
{
cout << m_Name << " loses. ";
}
void Player::Push() const
{
cout << m_Name << " pushes. ";
}
// The House Class
class House : public GenericPlayer
{
public:
House(const string& name = "House");
virtual ~House();
// indicates whether house is hitting - will always hit on 16 or less
virtual bool IsHitting() const;
// flips over the first card
void FlipFirstCard();
};
House::House(const string& name):
GenericPlayer(name)
{}
House::~House()
{}
bool House::IsHitting() const
{
return (GetTotal() <= 16);
}
void House::FlipFirstCard()
{
if (!(m_Cards.empty()))
{
m_Cards[0] -> Flip();
}
else
{
cout << "No card to flip! ";
}
}
//The 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& aHand);
};
Deck::Deck()
{
m_Cards.reserve(52);
Populate();
}
Deck::~Deck()
{}
void Deck::Populate()
{
Clear();
// create standard deck
for (int s = Card::CLUBS; s <= Card::SPADES; ++s)
{
for (int r= Card::ACE; r <= Card::KING; ++r)
{
Add(new Card(static_cast<Card::rank>(r), static_cast<Card:: suit > (s)));
}
}
}
void Deck::Shuffle()
{
random_shuffle(m_Cards.begin(), m_Cards.end());
}
void Deck::Deal(Hand& aHand)
{
if (!m_Cards.empty())
{
aHand.Add(m_Cards.back());
m_Cards.pop_back();
}
else
{
cout << "Out of cards. Unable to deal.";
}
}
// The Game Class
class Game
{
public:
Game(const vector<string> & names);
~Game();
// plays the game of blackjack
void Play();
private:
Deck m_Deck;
House m_House;
vector<Player> m_Players;
};
Game::Game(const vector<string>& names)
{
// create a vector of players from a vector of names
vector<string>::const_iterator pName;
for (pName = names.begin(); pName != names.end(); ++pName)
{
m_Players.push_back(Player(*pName));
}
// seed the random number generator
srand(static_cast<unsigned int>(time(0)));
m_Deck.Populate();
m_Deck.Shuffle();
}
Game::~Game()
{}
void Game::Play()
{
// deal initiL 5 cards to everyone
vector<Player>::iterator pPlayer;
for (int i = 0; i < 5; ++i)
{
for (pPlayer = m_Players.begin(); pPlayer != m_Players.end(); ++pPlayer)
{
m_Deck.Deal(*pPlayer);
}
m_Deck.Deal(m_House);
}
// display everyone's hand
for (pPlayer = m_Players.begin(); pPlayer != m_Players.end(); ++pPlayer)
{
cout << *pPlayer << endl;
}
cout << m_House << endl;
// remove everyone's cards
for (pPlayer = m_Players.begin(); pPlayer != m_Players.end(); ++pPlayer)
{
pPlayer -> Clear();
}
m_House.Clear();
}
// The Main Function
// function prototypes
ostream& operator << (ostream& os, const Card& aCard);
ostream& operator << (ostream& os, const GenericPlayer& aGenericPlayer);
int main()
{
cout << " Welcome to Blackjack! ";
int numPlayers = 1;
vector<string> names;
string name;
for (int i = 0; i < numPlayers; ++i)
{
cout << "Enter player name: ";
cin >> name;
names.push_back(name);
}
cout << endl;
// the game loop
Game aGame(names);
char again = 'y';
while (again != 'n' && again != 'N')
{
aGame.Play();
cout << " Do you want to play again? (Y/N): ";
cin >> again;
}
system("pause>nul");
return 0;
}
// Overloading the Operator <<() Function
// Overloads << operator so Card object can be sent to cout
ostream& operator << (ostream& os, const Card& aCard)
{
string x;
const string RANKS[] = {"0", "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"};
const string SUITS[] = {x=3, x=4, x=5, x=6};
if (aCard.m_IsFaceUp)
{
os << RANKS[aCard.m_Rank] << SUITS[aCard.m_Suit];
}
else
{
os << "XX";
}
return os;
}
// overloads << operator so a GenericPlayer object can be sent to cout
ostream& operator << (ostream& os, const GenericPlayer& aGenericPlayer)
{
os << aGenericPlayer.m_Name << ": ";
vector<Card*>::const_iterator pCard;
if (!aGenericPlayer.m_Cards.empty())
{
for (pCard = aGenericPlayer.m_Cards.begin();
pCard != aGenericPlayer.m_Cards.end(); ++pCard)
{
os << *(*pCard) << " ";
}
if (aGenericPlayer.GetTotal() != 0)
{
cout << "(" << aGenericPlayer.GetTotal() << ")";
}
}
else
{
os << "<empty>";
}
return os;
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.