Home | Notes | Projects > Console Blackjack
An interactive console Blackjack game implemented using Objecct-Oriented Design (OOD) and programming (OOP) in C++
To experience Object-Oriented Design process in a software development process.
Generate
UML class diagram
UML sequence diagram
To get familiar with Object-Oriented Programming concepts.
4 pillars of OOP - Encapsulation, Inheritance, Polymorphism, Abstraction
[!] Note: Demonstration video is to be uploaded.
In the meantime, following snapshots will give you an idea how it looks!



Operating System
Ubuntu 22.04.1 LTS (Kernel version: 5.15.0-52-generic)
Compiler
GCC version 11.3.0 (Ubuntu 11.3.0-1ubuntu1~22.04)
Debugger
GDB version 12.0.90 (Ubuntu 12.0.90-0ubuntu1)
[!] Note: This application compiles and runs on both Linux and Windows operating systems.

Sequence Diagram run()

Sequence Diagram init()

Sequence Diagram play()

Sequence Diagram reset()

main_Blackjack.cpp (Test Driver)
xxxxxxxxxx181//========================================================================================2// File Name : main_Backjack.cpp3// Description : OOP C++ BlackJack Program - Driver4// Author : Kyungjae Lee5// History : 11/08/2022 - File created.6//========================================================================================7
8910
11int main(int argc, char *argv[])12{13 BlackJack blackjack;14
15 blackjack.run();16
17 return 0;18}Blackjack.hpp
xxxxxxxxxx1741//========================================================================================2// File Name : BlackJack.hpp3// Description : OOP C++ BlackJack Program - BlackJack class implementation4// Author : Kyungjae Lee5// History : 11/03/2022 - File created.6//========================================================================================7
8910
111213
14151617
18class BlackJack19{20public:21 BlackJack();22 ~BlackJack();23 void init();24 void play();25 void reset();26 void run();27 void printResult(const int) const;28
29private:30 Dealer dealer;31 Player player;32};33
34// default constructor35BlackJack::BlackJack()36{37 // empty38}39
40// destructor41BlackJack::~BlackJack()42{43 // empty44}45
46// initializes the Blackjack game47void BlackJack::init()48{49 // screen clear for Windows OS50 51 std::system("cls");52 53 std::system("clear");54 55
56 dealer.printMsg("OK, let's begin!");57
58 // dealer deals initial hand59 for (int i = 0; i < 2; ++i)60 {61 dealer.addCard(dealer.deal());62 player.addCard(dealer.deal());63 }64
65 // print the dealer's hand (top card only) and palyer's hand66 std::cout << "Dealer's top card: "; dealer.printTopCard(); std::cout << std::endl;67 std::cout << "Your initial hand: "; player.printHand(); std::cout << std::endl;68}69
70// plays the Blackjack game71void BlackJack::play()72{73 // ask the player to choose between hit or stay74 dealer.printQuestion("Q. Hit or stay?");75 dealer.takeInput(player, "hit", "stay");76
77 while (player.getAnswer() == "hit")78 {79 // dealer deals another card to the player80 player.addCard(dealer.deal());81
82 // print the dealer's hand (top card only) and palyer's hand83 std::cout << "Dealer's top card: "; dealer.printTopCard(); std::cout << std::endl;84 std::cout << "Your current hand: "; player.printHand(); std::cout << std::endl;85
86 // if the player goes bust87 if (player.isBust())88 {89 player.setResult(LOOSE); // set the player's game result as LOOSE90 break;91 }92
93 // ask the user to choose between hit or stay94 dealer.printQuestion("Q. Hit or stay?");95 dealer.takeInput(player, "hit", "stay");96 }97
98 // if the player stays99 if (player.getResult() != LOOSE)100 {101 std::cout << "Dealer's current hand: "; dealer.printHand(); std::cout << std::endl;102
103 // if dealer's hand value totals to less than 17104 if (dealer.getHandValue() < 17)105 {106 std::cout << "Dealer's hand totals to less than 17. "107 << "Dealing him/herself another card." << std::endl;108
109 dealer.addCard(dealer.deal()); // deal him/herself another card110
111 // print the dealer's updated hand112 std::cout << "Dealer's updated hand: "; dealer.printHand(); std::cout << std::endl;113 }114
115 // if the dealer goes bust116 if (dealer.isBust())117 player.setResult(WIN); // set the player's game result to WIN118 // if both dealer and player is alive, compare hands and set player's game result119 // accordingly120 else121 player.setResult(dealer.compareHands(player));122 }123
124 // print the game result125 std::cout << std::endl; printResult(player.getResult()); std::cout << std::endl;126}127
128// resets the card deck and player's game result for (potentially) the next game129void BlackJack::reset()130{131 dealer.resetDeck(player);132 player.setResult(DEFAULT_RESULT); // DEFAULT_RESULT is any value that is not -1, 0, 1133}134
135// runs the Blackjack game136void BlackJack::run()137{138 // print the welcome message139 dealer.printMsg("***** Welcome to KJ's Console Casino! *****");140 dealer.printQuestion("Q. Would you like to play a game of Blackjack?");141 dealer.takeInput(player, "yes", "no");142
143 while (player.getAnswer() == "yes")144 {145 init();146 play();147 reset();148
149 // ask the player if he/she wants to play the game again and read in the input150 dealer.printQuestion("Q. Would you like to play another round?");151 dealer.takeInput(player, "yes", "no");152 }153
154 // print the goodbye message155 dealer.printMsg("***** Thanks for Playing! Good Bye~ *****");156}157
158// prints the game result159void BlackJack::printResult(const int result) const160{161 int value;162 std::cout << "Game has ended!" << std::endl;163 std::cout << "Dealer's hand: "; dealer.printHand(); std::cout << std::endl;164 std::cout << "Your hand : "; player.printHand(); std::cout << std::endl;165
166 if (result == WIN)167 std::cout << ">>> You win!" << std::endl;168 else if (result == TIE)169 std::cout << ">>> It's a tie!" << std::endl;170 else171 std::cout << ">>> You lost!" << std::endl;172}173
174Participants.hpp
xxxxxxxxxx1741//========================================================================================2// File Name : BlackJack.hpp3// Description : OOP C++ BlackJack Program - BlackJack class implementation4// Author : Kyungjae Lee5// History : 11/03/2022 - File created.6//========================================================================================7
8910
111213
14151617
18class BlackJack19{20public:21 BlackJack();22 ~BlackJack();23 void init();24 void play();25 void reset();26 void run();27 void printResult(const int) const;28
29private:30 Dealer dealer;31 Player player;32};33
34// default constructor35BlackJack::BlackJack()36{37 // empty38}39
40// destructor41BlackJack::~BlackJack()42{43 // empty44}45
46// initializes the Blackjack game47void BlackJack::init()48{49 // screen clear for Windows OS50 51 std::system("cls");52 53 std::system("clear");54 55
56 dealer.printMsg("OK, let's begin!");57
58 // dealer deals initial hand59 for (int i = 0; i < 2; ++i)60 {61 dealer.addCard(dealer.deal());62 player.addCard(dealer.deal());63 }64
65 // print the dealer's hand (top card only) and palyer's hand66 std::cout << "Dealer's top card: "; dealer.printTopCard(); std::cout << std::endl;67 std::cout << "Your initial hand: "; player.printHand(); std::cout << std::endl;68}69
70// plays the Blackjack game71void BlackJack::play()72{73 // ask the player to choose between hit or stay74 dealer.printQuestion("Q. Hit or stay?");75 dealer.takeInput(player, "hit", "stay");76
77 while (player.getAnswer() == "hit")78 {79 // dealer deals another card to the player80 player.addCard(dealer.deal());81
82 // print the dealer's hand (top card only) and palyer's hand83 std::cout << "Dealer's top card: "; dealer.printTopCard(); std::cout << std::endl;84 std::cout << "Your current hand: "; player.printHand(); std::cout << std::endl;85
86 // if the player goes bust87 if (player.isBust())88 {89 player.setResult(LOOSE); // set the player's game result as LOOSE90 break;91 }92
93 // ask the user to choose between hit or stay94 dealer.printQuestion("Q. Hit or stay?");95 dealer.takeInput(player, "hit", "stay");96 }97
98 // if the player stays99 if (player.getResult() != LOOSE)100 {101 std::cout << "Dealer's current hand: "; dealer.printHand(); std::cout << std::endl;102
103 // if dealer's hand value totals to less than 17104 if (dealer.getHandValue() < 17)105 {106 std::cout << "Dealer's hand totals to less than 17. "107 << "Dealing him/herself another card." << std::endl;108
109 dealer.addCard(dealer.deal()); // deal him/herself another card110
111 // print the dealer's updated hand112 std::cout << "Dealer's updated hand: "; dealer.printHand(); std::cout << std::endl;113 }114
115 // if the dealer goes bust116 if (dealer.isBust())117 player.setResult(WIN); // set the player's game result to WIN118 // if both dealer and player is alive, compare hands and set player's game result119 // accordingly120 else121 player.setResult(dealer.compareHands(player));122 }123
124 // print the game result125 std::cout << std::endl; printResult(player.getResult()); std::cout << std::endl;126}127
128// resets the card deck and player's game result for (potentially) the next game129void BlackJack::reset()130{131 dealer.resetDeck(player);132 player.setResult(DEFAULT_RESULT); // DEFAULT_RESULT is any value that is not -1, 0, 1133}134
135// runs the Blackjack game136void BlackJack::run()137{138 // print the welcome message139 dealer.printMsg("***** Welcome to KJ's Console Casino! *****");140 dealer.printQuestion("Q. Would you like to play a game of Blackjack?");141 dealer.takeInput(player, "yes", "no");142
143 while (player.getAnswer() == "yes")144 {145 init();146 play();147 reset();148
149 // ask the player if he/she wants to play the game again and read in the input150 dealer.printQuestion("Q. Would you like to play another round?");151 dealer.takeInput(player, "yes", "no");152 }153
154 // print the goodbye message155 dealer.printMsg("***** Thanks for Playing! Good Bye~ *****");156}157
158// prints the game result159void BlackJack::printResult(const int result) const160{161 int value;162 std::cout << "Game has ended!" << std::endl;163 std::cout << "Dealer's hand: "; dealer.printHand(); std::cout << std::endl;164 std::cout << "Your hand : "; player.printHand(); std::cout << std::endl;165
166 if (result == WIN)167 std::cout << ">>> You win!" << std::endl;168 else if (result == TIE)169 std::cout << ">>> It's a tie!" << std::endl;170 else171 std::cout << ">>> You lost!" << std::endl;172}173
174Dealer.hpp
xxxxxxxxxx1331//========================================================================================2// File Name : Dealer.hpp3// Description : OOP C++ BlackJack Program - Dealer class implementation4// - Dealer class is a derived class of Participant class5// Author : Kyungjae Lee6// History : 11/03/2022 - File created.7// 11/08/2022 - Text processor functionality separated to independent8// module.9//========================================================================================10
111213
1415161718
19class Dealer : public Participant20{21public:22 Dealer();23 ~Dealer();24 Card* deal();25 void printTopCard() const;26 int compareHands(Player&) const;27 void resetDeck(Player&);28 void printMsg(const std::string&) const;29 void printQuestion(const std::string&) const;30 void printClarificationMsg(const std::string&, const std::string&) const;31 void takeInput(Player&, const std::string&, const std::string&);32
33private:34 CardDeck deck;35 TextProcessor textProc; // processes player's natural language text input36};37
38// default constructor39Dealer::Dealer()40 : deck()41{42 // empty43}44
45// destructor46Dealer::~Dealer()47{48 // empty49}50
51// deals (returns) the top card of the card deck52// - receiver of the dealt card should process the card from its end53Card* Dealer::deal()54{55 Card *pcard = deck.topCard();56 deck.popTopCard();57
58 return pcard;59}60
61// prints the top card to the screen62void Dealer::printTopCard() const63{64 hand.front()->print(); std::cout << ".";65}66
67// compares the dealer's hand with the player's hand and returns the result68int Dealer::compareHands(Player& player) const69{70 if (player.getHandValue() > getHandValue())71 return 1;72 else if (player.getHandValue() == getHandValue())73 return 0;74 else75 return -1;76}77
78// resets the card deck79void Dealer::resetDeck(Player& player)80{81 for (Card* pcard : player.hand)82 deck.addBottom(pcard);83
84 for (Card* pcard : hand)85 deck.addBottom(pcard);86
87 player.hand.clear();88 hand.clear();89
90 deck.shuffle();91}92
93// prints the passed message to the screen (non-question type)94void Dealer::printMsg(const std::string& message) const95{96 std::cout << message << std::endl;97}98
99// prints the passed question to the screen (question type)100void Dealer::printQuestion(const std::string& question) const101{102 std::cout << question << std::endl << "> ";103}104
105// prints the clarification message to the screen106// - this should be called when the processed answer of the player does not match any107// keywords registered in the textMap108void Dealer::printClarificationMsg(const std::string& expected1,109 const std::string& expected2) const110{111 std::cout << "Q. I'm sorry, was that a " << expected1 << " or " << expected2 << "?"112 << std::endl << "> ";113}114
115// takes the player's input and processes it116void Dealer::takeInput(Player& player, const std::string& expected1,117 const std::string& expected2)118{119 std::string input;120 std::getline(std::cin, input);121
122 // asks for player's input repeatedly until the input is recognized by processText()123 while ((input = textProc.processText(input, expected1, expected2)) == "TEXT NOT RECOGNIZABLE")124 {125 printClarificationMsg(expected1, expected2);126 std::getline(std::cin, input);127 }128
129 // sets the player's member variable 'answer' to the recognized and processed input130 player.setAnswer(input);131}132
133Player.hpp
xxxxxxxxxx711//========================================================================================2// File Name : Player.hpp3// Description : OOP C++ BlackJack Program - Player class implementation4// - Player class is a derived class of Participant class5// Author : Kyungjae Lee6// History : 11/03/2022 - File created.7//========================================================================================8
91011
121314
15// can be any value that is not -1(loose), 0(tie), or win(1)16
17class Player : public Participant18{19public:20 Player();21 ~Player();22 void setAnswer(std::string);23 const std::string getAnswer() const;24 void setResult(int);25 const int getResult() const;26
27private:28 std::string answer; // stores the player's answer to the dealer's question29 int result; // stores the player's game result (win, tie, loose)30
31 friend class Dealer; // enables dealer's access to player's hand when resetting32};33
34// default constructor35Player::Player()36 : result(DEFAULT_RESULT)37{38 // empty39}40
41// destructor42Player::~Player()43{44 // empty45}46
47// sets the player's answer to the passed string48void Player::setAnswer(std::string answer)49{50 this->answer = answer;51}52
53// gets the player's answer54const std::string Player::getAnswer() const55{56 return answer;57}58
59// sets the player's game result to the passed integer value60void Player::setResult(int result)61{62 this->result = result;63}64
65// gets the player's game result66const int Player::getResult() const67{68 return result;69}70
71Card.hpp
xxxxxxxxxx991//========================================================================================2// File Name : Card.hpp3// Description : OOP C++ BlackJack Program - Card class implementation4// Author : Kyungjae Lee5// History : 11/03/2022 - File created.6//========================================================================================7
8910
11class Card12{13public:14 enum Suits {15 HEARTS, DIAMONDS, CLUBS, SPADES16 };17 enum Ranks {18 TWO = 2, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING, ACE19 };20 Card(Ranks, Suits);21 ~Card();22 Ranks getRank() const;23 Suits getSuit() const;24 int getValue() const;25 void print() const;26
27private:28 Ranks rank;29 Suits suit;30 int value;31};32
33// parameterized constructor34Card::Card(Ranks r, Suits s)35 : rank(r), suit(s)36{37 // empty38}39
40// destructor41Card::~Card()42{43 // empty44}45
46// gets the rank of the card47Card::Ranks Card::getRank() const48{49 return rank;50}51
52// gets the suit of the card53Card::Suits Card::getSuit() const54{55 return suit;56}57
58// gets the value of the card59int Card::getValue() const60{61 if (rank <= TEN)62 return rank;63 else if (rank == JACK)64 return 10;65 else if (rank == QUEEN)66 return 10;67 else if (rank == KING)68 return 10;69 else70 return 11; // ACE will be evaluted to 1 if necessary by the participants71}72
73// prints the card to the screen74void Card::print() const75{76 if (rank <= TEN)77 std::cout << rank;78 else if (rank == JACK)79 std::cout << "Jack";80 else if (rank == QUEEN)81 std::cout << "Queen";82 else if (rank == KING)83 std::cout << "King";84 else85 std::cout << "Ace";86
87 std:: cout << "-of-";88
89 if (suit == HEARTS)90 std::cout << "Hearts";91 else if (suit == DIAMONDS)92 std::cout << "Diamonds";93 else if (suit == CLUBS)94 std::cout << "Clubs";95 else96 std::cout << "Spades";97}98
99CardDeck.hpp
xxxxxxxxxx781//========================================================================================2// File Name : CardDeck.hpp3// Description : OOP C++ BlackJack Program - CardDeck class implementation4// Author : Kyungjae Lee5// History : 11/03/2022 - File created.6//========================================================================================7
8910
1112// shuffle13// default_randome_engine14// time151617
18class CardDeck19{20public:21 CardDeck();22 ~CardDeck();23 void shuffle();24 Card* topCard();25 void popTopCard();26 void addBottom(Card*);27
28private:29 std::deque<Card*> deck;30};31
32// default constructor33CardDeck::CardDeck()34 : deck()35{36 for (int r = 2; r <= 14; ++r)37 {38 for (int s = 0; s <= 3; ++s)39 deck.push_back(new Card(static_cast<Card::Ranks>(r), static_cast<Card::Suits>(s)));40 }41
42 shuffle();43}44
45// destructor46CardDeck::~CardDeck()47{48 for (Card* pcard : deck)49 delete pcard;50
51 deck.clear();52}53
54// shuffles the card deck55void CardDeck::shuffle()56{57 std::shuffle(deck.begin(), deck.end(), std::default_random_engine(time(NULL)));58}59
60// returns the top card in the deck61Card* CardDeck::topCard()62{63 return deck.front();64}65
66// removes the top card from the card deck67void CardDeck::popTopCard()68{69 deck.pop_front();70}71
72// add the passed card to the bottom of the card deck73void CardDeck::addBottom(Card* pcard)74{75 return deck.push_back(pcard);76}77
78TextProcessor.hpp
xxxxxxxxxx1021//========================================================================================2// File Name : TextProcessor.hpp3// Description : OOP C++ BlackJack Program - TextProcessor class implementation4// - TextProcessor processes player's natural language input text5// Author : Kyungjae Lee6// History : 11/08/2022 - File created.7//========================================================================================8
91011
121314
15class TextProcessor16{17public:18 TextProcessor();19 ~TextProcessor();20 void buildTextMap();21 std::string& processText(std::string&, const std::string&, const std::string&);22
23private:24 std::unordered_map<std::string, std::string> textMap;25};26
27// default constructor28TextProcessor::TextProcessor()29 : textMap()30{31 buildTextMap();32}33
34// destructor35TextProcessor::~TextProcessor()36{37 // empty38}39
40// builds the textMap41// - this textMap will be used for natural language processing42void TextProcessor::buildTextMap()43{44 textMap["yes"] = "yes";45 textMap["y"] = "yes";46 textMap["sure"] = "yes";47 textMap["yeah"] = "yes";48 textMap["yeap"] = "yes";49 textMap["yup"] = "yes";50 textMap["please"] = "yes";51 textMap["of course"] = "yes";52 textMap["nope"] = "no";53 textMap["nah"] = "no";54 textMap["no"] = "no";55 textMap["n"] = "no";56 textMap["hit"] = "hit";57 textMap["h"] = "hit";58 textMap["stay"] = "stay";59 textMap["stop"] = "stay";60 textMap["s"] = "stay";61}62
63// processes the natural language passed as a string, returns the processing result64// - takes the user input string, matches it with the expected answers registered in the65// textMap, returns the processed answer if the match was successful,66// "TEXT NOT RECOGNIZABLE" otherwise67std::string& TextProcessor::processText(std::string& input, const std::string& expected1,68 const std::string& expected2)69{70 std::vector<std::string> tokens;71 std::string token;72
73 // switch all characters of the input string to lower case74 for (auto& ch : input)75 ch = tolower(ch);76
77 std::stringstream ss(input);78
79 // tokenize the input string, search each token for its match in the textMap80 while (getline(ss, token, ' '))81 tokens.push_back(token);82
83 // if matched, return the matched string's pre-defined meaning84 for (auto tok : tokens)85 {86 if (textMap.find(tok) != textMap.end())87 {88 input = textMap[tok];89 break;90 }91 }92
93 // if the processed input matches any of the expected strings94 if (input == expected1 || input == expected2)95 return input; // return the input96
97 // if the processed input does not match any of the expected strings98 input = "TEXT NOT RECOGNIZABLE"; // signal the caller99 return input;100}101
102