I developed a blackjack game. I am relatively new to c++ and OOP, so I am asking for feedback on what could be improved. This game features betting, taking a card, standing, and splitting a hand. Besides, it also has a dealer that takes when his hand is under 17 and stands when it is over.
#include <bits/stdc++.h>
using namespace std;
class Card {
private:
int cardNum;
int cardType;
int value;
string name;
public:
Card(int ct, int cn);
~Card() {}
int getType() {return cardType;}
int getNum() {return cardNum;}
int getVal() {return value;}
string getName() {return name;}
};
Card::Card(int ct, int cn) : cardNum(cn), cardType(ct) {
if(cardNum == 1) {
value = 11;
} else if(cardNum >= 10) {
value = 10;
} else value = cardNum;
switch(cardNum) {
case 1 :
name = "ace";
break;
case 11 :
name = "jack";
break;
case 12 :
name = "queen";
break;
case 13 :
name = "king";
break;
default:
name = to_string(cardNum);
break;
}
switch(cardType) {
case 1 :
name.append(" of clubs");
break;
case 2 :
name.append(" of diamonds");
break;
case 3 :
name.append(" of hearts");
break;
case 4 :
name.append(" of spades");
break;
}
}
class Deck {
private:
const int deckSize = 52;
vector<Card*> deck;
int pos;
public:
Deck();
~Deck();
void shuffle(); //{random_shuffle(deck.begin(), deck.end());}
Card* getCard();
};
Deck::Deck() : pos(0) {
deck.reserve(deckSize);
for(int i = 1; i <= 4; i++) {
for(int j = 1; j <= 13; j++) {
deck.push_back(new Card(i, j));
}
}
}
Deck::~Deck() {
for(auto i : deck) {
delete i;
}
}
void Deck::shuffle() {
for(long long unsigned i = 0; i < deck.size(); i++) {
swap(deck[i], deck[rand()%deck.size()]);
}
}
Card* Deck::getCard() {
if(pos >= deckSize) {
shuffle();
pos = 0;
}
return deck[pos++];
}
class Hand {
private:
Deck* deck;
vector<Card*> cards;
int points;
unordered_set<Card*> aces;
public:
Hand(Deck* d) : deck(d), points(0) {}
~Hand() {}
void clearHand();
void addCard();
void addSpecificCard(Card* c);
int getPoints() {return points;}
Card* removeCard();
vector<Card*> getCards() {return cards;}
};
void Hand::clearHand() {
points = 0;
aces = unordered_set<Card*>();
cards = vector<Card*>();
}
void Hand::addCard() {
cards.push_back(deck->getCard());
if(cards.back()->getNum() == 1) aces.insert(cards.back());
points += cards.back()->getVal();
if(points > 21) {
while(!aces.empty() && points > 21) {
points -= 10;
aces.erase(aces.begin());
}
}
}
void Hand::addSpecificCard(Card* c) {
cards.push_back(c);
if(c->getNum() == 1) aces.insert(c);
points+=c->getVal();
}
Card* Hand::removeCard() {
Card* lastCard = cards.back();
points -= lastCard->getVal();
if(lastCard->getNum() == 1) aces.erase(lastCard);
cards.pop_back();
return lastCard;
}
class Dealer{
private:
Hand* hand;
public:
Dealer(Deck* d) : hand(new Hand(d)) {}
~Dealer() {delete hand;}
void getNewHand() {hand->clearHand();}
void addCard() {return hand->addCard();}
string makeTurn();
int getScore() {return hand->getPoints();}
Hand* getHand() {return hand;}
};
string Dealer::makeTurn() {
if(hand->getPoints() < 17) {
hand->addCard();
return "hit";
}
return "stand";
}
class House {
private:
Deck* deck;
vector<Hand*> hands;
Dealer* dealer;
private:
float playNewGame();
public:
House() : deck(new Deck()), dealer(new Dealer(deck)) {}
~House() {delete deck; delete dealer;}
void playBlackJack();
};
float House::playNewGame() {
deck->shuffle();
Hand* curHand = new Hand(deck);
hands.push_back(curHand);
hands[0]->addCard();
hands[0]->addCard();
dealer->addCard();
cout << "DEALERS first card: ";
cout << dealer->getHand()->getCards().back()->getName() << endl;
dealer->addCard();
if(hands[0]->getPoints() == 21) {
if(dealer->getScore() == 21) {
cout << "YOU and the DEALER have TIED ";
for(auto i : hands[0]->getCards()) cout << i->getName() << "; ";
cout << endl;
for(auto i : hands) {
delete i;
}
hands.clear();
dealer->getNewHand();
return 1;
} else {
cout << "YOU have WON with hand: ";
for(auto i : hands[0]->getCards()) cout << i->getName() << "; ";
cout << endl;
for(auto i : hands) {
delete i;
}
hands.clear();
dealer->getNewHand();
return 1.5;
}
}
unordered_set<Hand*> validHands;
validHands.insert(curHand);
float multiplier = 0;
string answer = "placeholder";
long long unsigned iter = 0;
while((answer != "no") && (iter < hands.size())) {
if((hands[iter]->getCards()[0]->getNum() != 1) &&
(hands[iter]->getCards()[1]->getNum() != 1) &&
(hands[iter]->getCards()[0]->getNum() == hands[iter]->getCards()[1]->getNum())) {
cout << "YOUR HAND: ";
for(auto i : hands[iter]->getCards()) cout << i->getName() << "; ";
cout << "SCORE = " << hands[0]->getPoints() << endl;
answer = "placeholder";
while(answer != "yes" && answer != "no") {
cout << "split? yes/no" << endl;
cin >> answer;
}
if(answer == "yes") {
Hand* newHand = new Hand(deck);
newHand->addSpecificCard(curHand->removeCard());
newHand->addCard();
curHand->addCard();
hands.push_back(newHand);
curHand = newHand;
validHands.insert(curHand);
}
}
iter++;
}
answer = "hit";
bool isUnder = false;
while(answer == "hit" || answer != "stand") {
auto hand = validHands.cbegin();
while(hand != validHands.end()) {
cout << " YOUR HAND: ";
for(auto i : (*hand)->getCards()) cout << i->getName() << "; ";
cout << "with SCORE = " << (*hand)->getPoints() << endl;
cout << "hit? hit/stand" << endl;
cin >> answer;
if(answer == "hit") {
(*hand)->addCard();
if((*hand)->getPoints() > 21) {
cout << "YOU have LOST with hand: ";
for(auto i : (*hand)->getCards()) cout << i->getName() << "; ";
cout << "with SCORE = " << (*hand)->getPoints() << endl;
hands.erase(find(hands.begin(), hands.end(), *hand));
multiplier -= 2;
hand = validHands.erase(hand);
if(hand == validHands.end()) answer = "stand";
} else if((*hand)->getPoints() == 21) {
cout << "YOU have hand: ";
for(auto i : (*hand)->getCards()) cout << i->getName() << "; ";
cout << "with SCORE = " << (*hand)->getPoints() << endl;
hand = validHands.erase(hand);
isUnder = true;
if(hand == validHands.end()) answer = "stand";
}
} else hand++;
}
}
if(validHands.empty() && !isUnder) return multiplier;
answer = "hit";
while(answer != "stand")
answer = dealer->makeTurn();
if(dealer->getScore() > 21) {
cout << "DEALER has LOST with hand: ";
for(auto i : dealer->getHand()->getCards()) cout << i->getName() << "; ";
cout << "with SCORE: " << dealer->getScore() << endl;
for(auto i : hands) {
delete i;
}
multiplier += 2* hands.size();
hands.clear();
dealer->getNewHand();
return multiplier;
}
for(auto hand : hands) {
cout << "your hand with hand SCORE = " << hand->getPoints() << " has ";
if(dealer->getScore() == hand->getPoints()) {
cout << "TIED with dealers hand: ";
for(auto i : dealer->getHand()->getCards()) cout << i->getName() << "; ";
cout << "with SCORE: " << dealer->getScore() << endl;
} else {
if(hand->getPoints() > dealer->getScore()) {
cout << "WON";
multiplier += 2;
} else {
cout << "LOST";
multiplier -= 2;
}
cout << " against the dealers hand: ";
for(auto i : dealer->getHand()->getCards()) cout << i->getName() << "; ";
cout << "with SCORE: " << dealer->getScore() << endl;
}
}
for(auto i : hands) {
delete i;
}
hands.clear();
dealer->getNewHand();
return multiplier;
}
void House::playBlackJack() {
float totalMoney = 1000;
cout << "your total money = " << totalMoney << endl;
string cashOut = "no";
while((totalMoney > 0) && (cashOut == "no" || cashOut != "yes")) {
int bet = INT_MAX;
while(bet > totalMoney) {
cout << "bet number?" << endl;
cin >> bet;
}
totalMoney += bet*playNewGame()/2;
cout << "your total money = " << totalMoney << endl;
if(totalMoney > 0) {
cout << "cash out? yes/no" << endl;
cin >> cashOut;
}
}
}
int main()
{
srand((time(0)));
House h;
h.playBlackJack();
return 0;
}