//----------------------------------------------- // Card, Deck and Player classes // This is in header (*.h) file(s) // Remember how header file guard look? #ifndef BLACKJACK_CLASSES_H #define BLACKJACK_CLASSES_H #include #include #include //----------------------------------------------- class Card { public: std::ostream& print(std::ostream& os); // "getter" functions access private parts safe int getValue() const { return value; } std::string getSuit() const { return suit; } int getBlackjackValue() const; private: friend class Deck; Card(int v, std::string s); int value; // 1 - 13 std::string suit; // hearts, diamonds, clubs, spades }; //----------------------------------------------- class Deck { public: Deck(); void shuffle(); Card top(); private: std::vector deck; // Create only one instance of random_device in your program, // creating several, or recreating one, will possibly yield // not-very-random numbers. // static: one for all instances of class static std::random_device rand; }; //----------------------------------------------- class Player { public: Player(std::string n); // default values in interface specification (header file) void draw(Deck& d, int count = 1); bool decideToHit(); bool blackjack() const { return sum == 21; } bool stands() const { return stopped; } bool busted() const { return sum > 21; } // const: no member variable is modified int getScore() const { return sum; } std::string getName() const { return name; } private: std::string name; int sum; bool stopped; }; #endif // end of header guard //----------------------------------------------- // Card, Deck and Player implementation // This is in implementation (*.cc) file(s) // Would #include "blackjack_classes.h" //----------------------------------------------- using namespace std; // Card member functions //------------------------------------- Card::Card(int v, string s) : value(v), suit(s) { // initializer list preferred over this // value = v; // suit = s; } // A long way toward operator<< ostream& Card::print(ostream& os) { return os << value << " of " << suit; } int Card::getBlackjackValue() const { return min(value, 10); } // Deck member functions and members //----------------------------------------------- // static member must be created once! random_device Deck::rand; Deck::Deck() { for (int v = 1; v <= 13; ++v) { deck.push_back(Card(v, "hearts")); deck.push_back(Card(v, "diamonds")); deck.push_back(Card(v, "spades")); deck.push_back(Card(v, "clubs")); } } // std::shuffle would work instead void Deck::shuffle() { for (int i = 0; i < 52; ++i) { swap(deck.at(i), deck.at( rand() % 52 )); } } Card Deck::top() { Card c = deck.back(); deck.pop_back(); return c; } // Player member functions //----------------------------------------------- Player::Player(string n) : name(n), sum(0), stopped(false) { // initializer list preferred over this // name = n; // sum = 0; // stopped = false; } bool Player::decideToHit() { string answer; cout << name << ", your score is " << sum << "." << endl; cout << "Do you want to take a hit? (Y/n) "; getline(cin, answer); bool hit = (answer.size() == 0 || answer == "y" || answer == "yes"); stopped = !hit; return hit; } void Player::draw(Deck& d, int count) { for (int i = 0; i < count; ++i) { Card card = d.top(); cout << name << " draws "; card.print(cout) << endl; if (card.getBlackjackValue() == 1 && (sum + 11) <= 21) sum += 11; else sum += card.getBlackjackValue(); if (sum > 21) { cout << name << " busted." << endl; } } } // A simplified implementation of the card game Blackjack // see wikipedia for full information of the game #include #include #include // sort using namespace std; //----------------------------------------------- // main program in it's own implementation file // Would #include "blackjack_classes.h" //----------------------------------------------- int main() { // discuss what happen when variables are declared Deck my_deck; // discuss how call to member function works my_deck.shuffle(); cout << "Welcome to the game of Blackjack!" << endl; vector v{ Player("One"), Player("Two"), Player("Three"), Player("Four"), Player("Five") }; unsigned int done = 0; // Start by drawing two cards... for ( Player& player : v) { player.draw(my_deck); player.draw(my_deck); } // Play the game... while ( done < v.size() ) { cout << endl << "Next round ----------------" << endl; done = 0; for ( Player& player : v) { if ( player.busted() ) { cout << player.getName() << " had gone bust!" << endl; ++done; } else if ( player.blackjack() ) { cout << player.getName() << " have Blackjack!" << endl; ++done; } else if ( player.stands() ) { cout << player.getName() << " stands." << endl; ++done; } else if ( player.decideToHit() ) { player.draw(my_deck); } else // Player choose to stand { ++done; } } } vector::iterator end; end = remove_if(v.begin(), v.end(), [](Player const& p)->bool { return p.getScore() > 21; }); v.erase(end, v.end()); sort(v.begin(), v.end(), [](Player const& a, Player const& b)->bool { return a.getScore() > b.getScore(); }); if ( v.size() == 0 ) { cout << "No winner!" << endl; } else { int winning_score = v.at(0).getScore(); unsigned int i{0}; while ( i < v.size() && v.at(i).getScore() == winning_score ) { cout << v.at(i).getName() << " wins! (score " << winning_score << ")" << endl; ++i; } } return 0; }