mkv

WHERE'S MY VIDEOGAME SKYE

mkv
Dec 8th, 2013
202
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.74 KB | None | 0 0
  1. /*
  2.  * Blackjack
  3.  * =========
  4.  * Plays a simple version of the casino game of blackjack; for 1 - 7 players
  5.  *
  6.  *
  7.  * REQ#1 OK
  8.  * Force the deck to repopulate before a
  9.  * round if the number of cards is running low.
  10.  *
  11.  * REQ#2 OK
  12.  * Create a way for players to bet money. Each player
  13.  * starts with $100. Keep track of player winnings.
  14.  *
  15.  * REQ#3 TODO?
  16.  * Create in the main program that allows players to
  17.  * continue playing with their current balance or cash.
  18.  *
  19.  */
  20.  
  21. #include <iostream>
  22. #include <string>
  23. #include <vector>
  24. #include <algorithm>
  25. #include <ctime>
  26.  
  27. using namespace std;
  28.  
  29. class Card
  30. {
  31. public:
  32.     enum rank {ACE = 1, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN,
  33.                JACK, QUEEN, KING};
  34.     enum suit {CLUBS, DIAMONDS, HEARTS, SPADES};
  35.  
  36.     //overloading << operator so can send Card object to standard output
  37.     friend ostream& operator<<(ostream& os, const Card& aCard);
  38.  
  39.     Card(rank r = ACE, suit s = SPADES, bool ifu = true);
  40.  
  41.     //returns the value of a card, 1 - 11
  42.     int GetValue() const;
  43.  
  44.     //flips a card; if face up, becomes face down and vice versa
  45.     void Flip();
  46.  
  47. private:
  48.     rank m_Rank;
  49.     suit m_Suit;
  50.     bool m_IsFaceUp;
  51. };
  52.  
  53. Card::Card(rank r, suit s, bool ifu):  m_Rank(r), m_Suit(s), m_IsFaceUp(ifu)
  54. {}
  55.  
  56. int Card::GetValue() const
  57. {
  58.     //if a cards is face down, its value is 0
  59.     int value = 0;
  60.     if (m_IsFaceUp)
  61.     {
  62.         //value is number showing on card
  63.         value = m_Rank;
  64.         //value is 10 for face cards
  65.         if (value > 10)
  66.         {
  67.             value = 10;
  68.         }
  69.     }
  70.     return value;
  71. }
  72.  
  73. void Card::Flip()
  74. {
  75.     m_IsFaceUp = !(m_IsFaceUp);
  76. }
  77.  
  78. class Hand
  79. {
  80. public:
  81.     Hand();
  82.  
  83.     virtual ~Hand();
  84.  
  85.     //adds a card to the hand
  86.     void Add(Card* pCard);
  87.  
  88.     //clears hand of all cards
  89.     void Clear();
  90.  
  91.     //gets hand total value, intelligently treats aces as 1 or 11
  92.     int GetTotal() const;
  93.  
  94. protected:
  95.     vector<Card*> m_Cards;
  96. };
  97.  
  98. Hand::Hand()
  99. {
  100.     m_Cards.reserve(7);
  101. }
  102.  
  103. Hand::~Hand()
  104. {
  105.     Clear();
  106. }
  107.  
  108. void Hand::Add(Card* pCard)
  109. {
  110.     m_Cards.push_back(pCard);
  111. }
  112.  
  113. void Hand::Clear()
  114. {
  115.     //iterate through vector, freeing all memory on the heap
  116.     vector<Card*>::iterator iter = m_Cards.begin();
  117.     for (iter = m_Cards.begin(); iter != m_Cards.end(); ++iter)
  118.     {
  119.         delete *iter;
  120.         *iter = 0;
  121.     }
  122.     //clear vector of pointers
  123.     m_Cards.clear();
  124. }
  125.  
  126. int Hand::GetTotal() const
  127. {
  128.     //if no cards in hand, return 0
  129.     if (m_Cards.empty())
  130.     {
  131.         return 0;
  132.     }
  133.  
  134.     //if a first card has value of 0, then card is face down; return 0
  135.     if (m_Cards[0]->GetValue() == 0)
  136.     {
  137.         return 0;
  138.     }
  139.  
  140.     //add up card values, treat each Ace as 1
  141.     int total = 0;
  142.     vector<Card*>::const_iterator iter;
  143.     for (iter = m_Cards.begin(); iter != m_Cards.end(); ++iter)
  144.     {
  145.         total += (*iter)->GetValue();
  146.     }
  147.  
  148.     //determine if hand contains an Ace
  149.     bool containsAce = false;
  150.     for (iter = m_Cards.begin(); iter != m_Cards.end(); ++iter)
  151.     {
  152.         if ((*iter)->GetValue() == Card::ACE)
  153.         {
  154.             containsAce = true;
  155.         }
  156.     }
  157.  
  158.     //if hand contains Ace and total is low enough, treat Ace as 11
  159.     if (containsAce && total <= 11)
  160.     {
  161.         //add only 10 since we've already added 1 for the Ace
  162.         total += 10;
  163.     }
  164.  
  165.     return total;
  166. }
  167.  
  168. class GenericPlayer : public Hand
  169. {
  170.     friend ostream& operator<<(ostream& os, const GenericPlayer& aGenericPlayer);
  171.  
  172. public:
  173.     GenericPlayer(const string& name = "");
  174.  
  175.     virtual ~GenericPlayer();
  176.  
  177.     //indicates whether or not generic player wants to keep hitting
  178.     virtual bool IsHitting() const = 0;
  179.  
  180.     //returns whether generic player has busted - has a total greater than 21
  181.     bool IsBusted() const;
  182.  
  183.     //announces that the generic player busts
  184.     void Bust() const;
  185.  
  186. protected:
  187.     string m_Name;
  188. };
  189.  
  190. GenericPlayer::GenericPlayer(const string& name):
  191.     m_Name(name)
  192. {}
  193.  
  194. GenericPlayer::~GenericPlayer()
  195. {}
  196.  
  197. bool GenericPlayer::IsBusted() const
  198. {
  199.     return (GetTotal() > 21);
  200. }
  201.  
  202. void GenericPlayer::Bust() const
  203. {
  204.     cout << m_Name << " busts.\n";
  205. }
  206.  
  207. class Player : public GenericPlayer
  208. {
  209. public:
  210.     Player(const string& name = "");
  211.  
  212.     virtual ~Player();
  213.  
  214.     //returns whether or not the player wants another hit
  215.     virtual bool IsHitting() const;
  216.  
  217.     //announces that the player wins.
  218.     //constness removed due to balance modification (REQ#2)
  219.     void Win();
  220.  
  221.     //announces that the player loses
  222.     //constness removed due to balance modification (REQ#2)
  223.     void Lose();
  224.  
  225.     //announces that the player pushes
  226.     //constness removed due to balance modification (REQ#2)
  227.     void Push();
  228.    
  229.     //returns the balance of this player (REQ#2)
  230.     int GetBalance() const;
  231.    
  232.     //returns the current bet of this player (REQ#2)
  233.     int GetBet() const;
  234.    
  235.     //ask player to bet (REQ#2)
  236.     void AskForBet();
  237.    
  238. private:
  239.     int m_Balance;
  240.     int m_Bet;
  241. };
  242.  
  243. Player::Player(const string& name):
  244.     GenericPlayer(name), m_Balance(100)
  245. {}
  246.  
  247. Player::~Player()
  248. {}
  249.  
  250. bool Player::IsHitting() const
  251. {
  252.     cout << m_Name << ", do you want a hit? (Y/N): ";
  253.     char response;
  254.     cin >> response;
  255.     return (response == 'y' || response == 'Y');
  256. }
  257.  
  258. //REQ#2 - Betting
  259. int Player::GetBalance() const
  260. {
  261.     return m_Balance;
  262. }
  263.  
  264. //REQ#2 - Betting
  265. int Player::GetBet() const
  266. {
  267.     return m_Bet;
  268. }
  269.  
  270. //REQ#2 - Betting
  271. void Player::AskForBet()
  272. {
  273.     cout << m_Name << ", you have $" << GetBalance() << ". Place your bet: $";
  274.     int response;
  275.     cin >> response;
  276.     if (m_Balance < response)
  277.     {
  278.         cout << "Bet is higher than balance. No can do!" << endl;
  279.         return AskForBet();
  280.     }
  281.     m_Bet = response;
  282.     m_Balance -= m_Bet;
  283. }
  284.  
  285. void Player::Win()
  286. {
  287.     m_Balance += m_Bet * 2;
  288.     cout << m_Name <<  " wins twice their bet of $"
  289.                    << GetBet() << ". Balance: $"
  290.                    << GetBalance() << "." << endl;
  291. }
  292.  
  293. void Player::Lose()
  294. {
  295.     cout << m_Name <<  " loses their bet of $"
  296.                    << GetBet() << ". Balance: $"
  297.                    << GetBalance() << "." << endl;
  298. }
  299.  
  300. void Player::Push()
  301. {
  302.     m_Balance += m_Bet;
  303.     cout << m_Name <<  " pushes, bet returned ($"
  304.                    << GetBet() << ". Balance: $"
  305.                    << GetBalance() << "." << endl;
  306. }
  307.  
  308. class House : public GenericPlayer
  309. {
  310. public:
  311.     House(const string& name = "House");
  312.  
  313.     virtual ~House();
  314.  
  315.     //indicates whether house is hitting - will always hit on 16 or less
  316.     virtual bool IsHitting() const;
  317.  
  318.     //flips over first card
  319.     void FlipFirstCard();
  320. };
  321.  
  322. House::House(const string& name):
  323.     GenericPlayer(name)
  324. {}
  325.  
  326. House::~House()
  327. {}
  328.  
  329. bool House::IsHitting() const
  330. {
  331.     return (GetTotal() <= 16);
  332. }
  333.  
  334. void House::FlipFirstCard()
  335. {
  336.     if (!(m_Cards.empty()))
  337.     {
  338.         m_Cards[0]->Flip();
  339.     }
  340.     else
  341.     {
  342.         cout << "No card to flip!\n";
  343.     }
  344. }
  345.  
  346. class Deck : public Hand
  347. {
  348. public:
  349.     Deck();
  350.  
  351.     virtual ~Deck();
  352.  
  353.     //create a standard deck of 52 cards
  354.     void Populate();
  355.  
  356.     //shuffle cards
  357.     void Shuffle();
  358.    
  359.     //returns low if getting low on cards
  360.     bool OutOfCards(int numPlayers);
  361.  
  362.     //deal one card to a hand
  363.     void Deal(Hand& aHand);
  364.  
  365.     //give additional cards to a generic player
  366.     void AdditionalCards(GenericPlayer& aGenericPlayer);
  367. };
  368.  
  369. Deck::Deck()
  370. {
  371.     m_Cards.reserve(52);
  372.     Populate();
  373. }
  374.  
  375. Deck::~Deck()
  376. {}
  377.  
  378. void Deck::Populate()
  379. {
  380.     Clear();
  381.     //create standard deck
  382.     for (int s = Card::CLUBS; s <= Card::SPADES; ++s)
  383.     {
  384.         for (int r = Card::ACE; r <= Card::KING; ++r)
  385.         {
  386.             Add(new Card(static_cast<Card::rank>(r),
  387.                          static_cast<Card::suit>(s)));
  388.         }
  389.     }
  390. }
  391.  
  392. void Deck::Shuffle()
  393. {
  394.     random_shuffle(m_Cards.begin(), m_Cards.end());
  395. }
  396.  
  397. //REQ#1 - Restock if dealer is low
  398. bool Deck::OutOfCards(int numPlayers)
  399. {
  400.     //Assume each player (and house) needs 7 cards
  401.     return m_Cards.size() < 7 * (numPlayers + 1);
  402. }
  403.  
  404. void Deck::Deal(Hand& aHand)
  405. {
  406.     if (!m_Cards.empty())
  407.     {
  408.         aHand.Add(m_Cards.back());
  409.         m_Cards.pop_back();
  410.     }
  411.     else
  412.     {
  413.         cout << "Out of cards. Unable to deal.";
  414.     }
  415. }
  416.  
  417. void Deck::AdditionalCards(GenericPlayer& aGenericPlayer)
  418. {
  419.     cout << endl;
  420.     //continue to deal a card as long as generic player isn't busted and
  421.     //wants another hit
  422.     while ( !(aGenericPlayer.IsBusted()) && aGenericPlayer.IsHitting() )
  423.     {
  424.         Deal(aGenericPlayer);
  425.         cout << aGenericPlayer << endl;
  426.  
  427.         if (aGenericPlayer.IsBusted())
  428.         {
  429.             aGenericPlayer.Bust();
  430.         }
  431.     }
  432. }
  433.  
  434. class Game
  435. {
  436. public:
  437.     Game(const vector<string>& names);
  438.  
  439.     ~Game();
  440.  
  441.     //plays the game of blackjack
  442.     void Play();
  443.  
  444. private:
  445.     Deck m_Deck;
  446.     House m_House;
  447.     vector<Player> m_Players;
  448. };
  449.  
  450. Game::Game(const vector<string>& names)
  451. {
  452.     //create a vector of players from a vector of names
  453.     vector<string>::const_iterator pName;
  454.     for (pName = names.begin(); pName != names.end(); ++pName)
  455.     {
  456.         m_Players.push_back(Player(*pName));
  457.     }
  458.  
  459.     //seed the random number generator
  460.     srand(static_cast<unsigned int>(time(0)));
  461.     m_Deck.Populate();
  462.     m_Deck.Shuffle();
  463. }
  464.  
  465. Game::~Game()
  466. {}
  467.  
  468. void Game::Play()
  469. {
  470.     //REQ#1 - Restock if dealer is low
  471.     if (m_Deck.OutOfCards(m_Players.size()))
  472.     {
  473.         cout << "Out of cards. Shuffling deck..." << endl;
  474.         m_Deck.Populate();
  475.         m_Deck.Shuffle();
  476.     }
  477.    
  478.     //deal initial 2 cards to everyone
  479.     vector<Player>::iterator pPlayer;
  480.     for (int i = 0; i < 2; ++i)
  481.     {
  482.         for (pPlayer = m_Players.begin(); pPlayer != m_Players.end(); ++pPlayer)
  483.         {
  484.             m_Deck.Deal(*pPlayer);
  485.         }
  486.         m_Deck.Deal(m_House);
  487.     }
  488.  
  489.     //REQ#2 - Ask for bet
  490.     for (pPlayer = m_Players.begin(); pPlayer != m_Players.end(); ++pPlayer)
  491.     {
  492.         pPlayer->AskForBet();
  493.     }
  494.  
  495.     //hide house's first card
  496.     m_House.FlipFirstCard();
  497.    
  498.     //display everyone's hand
  499.     for (pPlayer = m_Players.begin(); pPlayer != m_Players.end(); ++pPlayer)
  500.     {
  501.         cout << *pPlayer << endl;
  502.     }
  503.     cout << m_House << endl;
  504.  
  505.     //deal additional cards to players
  506.     for (pPlayer = m_Players.begin(); pPlayer != m_Players.end(); ++pPlayer)
  507.     {
  508.         m_Deck.AdditionalCards(*pPlayer);
  509.     }
  510.  
  511.     //reveal house's first card
  512.     m_House.FlipFirstCard();
  513.     cout << endl << m_House;
  514.  
  515.     //deal additional cards to house
  516.     m_Deck.AdditionalCards(m_House);
  517.  
  518.     if (m_House.IsBusted())
  519.     {
  520.         //everyone still playing wins
  521.         for (pPlayer = m_Players.begin(); pPlayer != m_Players.end(); ++pPlayer)
  522.         {
  523.             if ( !(pPlayer->IsBusted()) )
  524.             {
  525.                 pPlayer->Win();
  526.             }
  527.         }
  528.     }
  529.     else
  530.     {
  531.          //compare each player still playing to house
  532.         for (pPlayer = m_Players.begin(); pPlayer != m_Players.end();
  533.              ++pPlayer)
  534.         {
  535.             if ( !(pPlayer->IsBusted()) )
  536.             {
  537.                 if (pPlayer->GetTotal() > m_House.GetTotal())
  538.                 {
  539.                     pPlayer->Win();
  540.                 }
  541.                 else if (pPlayer->GetTotal() < m_House.GetTotal())
  542.                 {
  543.                     pPlayer->Lose();
  544.                 }
  545.                 else
  546.                 {
  547.                     pPlayer->Push();
  548.                 }
  549.             }
  550.         }
  551.  
  552.     }
  553.  
  554.     //remove everyone's cards
  555.     for (pPlayer = m_Players.begin(); pPlayer != m_Players.end(); ++pPlayer)
  556.     {
  557.         pPlayer->Clear();
  558.     }
  559.     m_House.Clear();
  560. }
  561.  
  562. //function prototypes
  563. ostream& operator<<(ostream& os, const Card& aCard);
  564. ostream& operator<<(ostream& os, const GenericPlayer& aGenericPlayer);
  565.  
  566. int main()
  567. {
  568.     cout << "\t\tWelcome to Blackjack!\n\n";
  569.  
  570.     int numPlayers = 0;
  571.     while (numPlayers < 1 || numPlayers > 7)
  572.     {
  573.         cout << "How many players? (1 - 7): ";
  574.         cin >> numPlayers;
  575.     }
  576.  
  577.     vector<string> names;
  578.     string name;
  579.     for (int i = 0; i < numPlayers; ++i)
  580.     {
  581.         cout << "Enter player name: ";
  582.         cin >> name;
  583.         names.push_back(name);
  584.     }
  585.     cout << endl;
  586.  
  587.     //the game loop
  588.     Game aGame(names);
  589.     char again = 'y';
  590.     while (again != 'n' && again != 'N')
  591.     {
  592.         aGame.Play();
  593.         cout << "\nDo you want to play again? (Y/N): ";
  594.         cin >> again;
  595.     }
  596.  
  597.     return 0;
  598. }
  599.  
  600. //overloads << operator so Card object can be sent to cout
  601. ostream& operator<<(ostream& os, const Card& aCard)
  602. {
  603.     const string RANKS[] = {"0", "A", "2", "3", "4", "5", "6", "7", "8", "9",
  604.                             "10", "J", "Q", "K"};
  605.     const string SUITS[] = {"c", "d", "h", "s"};
  606.  
  607.     if (aCard.m_IsFaceUp)
  608.     {
  609.         os << RANKS[aCard.m_Rank] << SUITS[aCard.m_Suit];
  610.     }
  611.     else
  612.     {
  613.         os << "XX";
  614.     }
  615.  
  616.     return os;
  617. }
  618.  
  619. //overloads << operator so a GenericPlayer object can be sent to cout
  620. ostream& operator<<(ostream& os, const GenericPlayer& aGenericPlayer)
  621. {
  622.     os << aGenericPlayer.m_Name << ":\t";
  623.  
  624.     vector<Card*>::const_iterator pCard;
  625.     if (!aGenericPlayer.m_Cards.empty())
  626.     {
  627.         for (pCard = aGenericPlayer.m_Cards.begin();
  628.              pCard != aGenericPlayer.m_Cards.end();
  629.              ++pCard)
  630.         {
  631.             os << *(*pCard) << "\t";
  632.         }
  633.  
  634.  
  635.         if (aGenericPlayer.GetTotal() != 0)
  636.         {
  637.             cout << "(" << aGenericPlayer.GetTotal() << ")";
  638.         }
  639.     }
  640.     else
  641.     {
  642.         os << "<empty>";
  643.     }
  644.  
  645.     return os;
  646. }
Advertisement
Add Comment
Please, Sign In to add comment