BlackJack game OOP for Final

I have to make a final project with a OOP. I made this so far but I have no Idea why some of the class can't be call from the main program. The error message is: cannot open source file of the Hand, Game, Deck, Player, genericPlayer. Also, they are undefined, this made me confused as I did define them from the class?
Thank you in advance for the help!

This is the main()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include<string>
#include <Hand.h>
#include <Game.h>
#include <Deck.h>
#include <Player.h>
#include <genericPlayer.h>
#include <Card.h>

using namespace std;

//function prototypes
ostream& operator<<(ostream& os, const Card& aCard);
ostream& operator<<(ostream& os, const GenericPlayer& aGenericPlayer);

int main()
{
	cout << "\t\tWelcome to blackjack!\n\n";
	int numPlayer = 0;
	while (numPlayer<1 || numPlayer > 7)
	{
		cout << "How many Player? (1-7): \n";
		cin >> numPlayers;
	}
	vector<string>names;
	string name;
	for (int i = 0; i < numPlayers; ++i)
	{
		cout << "Enter player name: \n";
		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 << "\n Do you want to play again? (Y/N): \n";
			cin >> again;
		}
	return 0;
}
Last edited on
Game Class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#pragma once
#ifndef GAME_H_
#define GAME_H_
#include <iostream>
#include<string>
#include <vector>
#include <algorithm>
#include <ctime>

using namespace std;

class Game
{
public:
	Game(const vector<string>& names);
	~Game();

	//plays the game of blackjakc
	void Play();
private:
	Deck m_Deck;
	House m_House;
	vector<Player> m_Player;
};

Game::Game(const vector<string>& names)
{
	//create a vector of player from a vector of ma,es
	vector<string>::const_iterator pName;
	for (pName = name.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 initial 2 cards to everyone
	vector<Player>::iterator pPlayer;
	for (int i = 0; i < 2; ++i)
	{
		for (pPlayer = m_Player.begin(); pPlayer != m_Players.end(); ++pPlayer)
		{
			m_Deck.Deal(*pPlayer);
		}
		m_Deck.Deal(m_House);
	}
	//hide house's first card
	m_House.FlipFirstCard();

	//dipslay everyone's hand
	for (pPlayer = m_Players.begin(); pPlayer != m_Players.end(); ++pPlayer)
	{
		cout << *pPlayer << endl;
	}
	cout << m_House << endl;
	// deal additional cards to players
	for (pPlayer = m_Players.begin(); pPlayer != m_Players.end(); ++pPlayer)
	{
		m_Deck.AdditionalCards(*pPlayer);
	}

	//reveal house's first card
	m_house.FlipFirstCard();
	cout << endl; << m_House;

	//deal additional cards to house
	m_deck.AdditionalCards(m_House);
	if (m_House.IsBusted())
	{
		//everyone still playing win
		for (pPlayer = m_Players.begin(); pPlayer != _Players.end(); ++pPlayer)
		{
			if (!(pPlayer->IsBusted()))
			{
				pPlayer->Win();
			}
		}
	}
	else
	{
		//compare each player still playing to house
		for (pPlayer = _Palyers.begin(); pPlayer != m_Players.end(); ++pPlayer)
		{
			if (!(pPlayer->IsBusted()))
			{
				pPlayer->Win();
			}
			else if (pPlayer->GetTotal() < m_House.GetTotal())
			{
				pPlayer->Lose();
			}
			else
			{
				pPlayer->Push();
			}
		}
	}
	//remove everyone cards
	for (pPlayer = m_Players.begin(); pPlayer != m_Players.edn(); ++pPlayer)
	{
		pPlayer->Clear();
	}
	m_House.Clear();
}
#endif
Deck Class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#pragma 
#ifndef DECK_H_
#define DECK_H_
#include <iostream>
#include<string>
#include <vector>
#include <algorithm>
#include <ctime>
#include <Hand.h>

using namespace std;

class Deck : public Hand
{
	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);

	//give additional cards to a generic plauer
	void AdditionalCards(GenericPlayer& aGenericPlayer);
};

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(0, m_Cards.end());
}

void Deck::Deal(Hand& aHand)
{
	if (!m_Cards.empty())
	{
		aHand.Add(m_Cards.bakc());
		m_Cards.pop_back();
	}
	else
	{
		cout << "Out of cards. Unable to deal. ";
	}
}

void Deck::AdditionalCards(GenericPlayer& aGenericPlayer)
{
	cout << endl;
	//continue to deal
	while (!(aGenericPlayer.IsBusted()) && aGenericPlayer.IsHitting())
	{
		Deal(aGenericPlayer);
		cout << aGenericPlayer << endl;
		if (aGenericPlayer.IsBusted())
		{
			aGenericPlayer.Bust();
		}
	}
}
#endif 
Player Class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#pragma once
#ifndef PLAYER_H_
#define PLAYER_H_
#include <iostream>
#include<string>
#include <vector>
#include <algorithm>
#include <ctime>
#include <genericPlayer.h>

using namespace std;

class Player : public GenericPlayer
{
public:
	Player(const string& name = "");
	virtual ~Player();

	//return whter or not the player wants another hit
	virtual bool IsHitting() const;

	//announces that the plaer 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)
{}
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::Lose() const
{
	cout << m_Name << " loses. \n";
}

void Player::Push() const
{
	cout << m_Name << " pushes. \n";
}
#endif 
GenericPlayer Class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#pragma once
#ifndef GENERICPLAYER_H_
#define GENERICPLAYER_H_
#include <string>
#include <fstream>
#include <iostream>
#include <Hand.h>

using namespace std;

class GenericPlayer : public Hand
{
	friend ostream& operator <<< (ostream& os, const GenericPlayer& aGenericPlayer);
public:
	GenericPlayer(const string& name = "");
	virtual ~GenericPlayer();

	//indicate whther or not player wan to keep hitting
	virtual bool IsHitting() const = 0;

	//return whether generic player has busted - has a totla greater than 21
	bool IsBusted() const;

	//announces that the player busts
	void Bust() const;

protected:
	string m_Name;
};

GenericPlayer::GenericPlayer(const string& name);
m_Name(name);
{}
GenericPlayer::~GenericPlayer()
{}
bool GenericPlayer::IsBusted() const
{
	return (GetTotal() > 21);
}
void Generic Player::Bust() const
{
	cout << m_Name << " busts. \n";
}
#endif 
Hand Class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#pragma once
#ifndef HAND_H_
#define HAND_H_
#include <iostream>
#include<string>
#include <vector>
#include <algorithm>
#include <ctime>

using namespace std;

class Hand
{
public:
	Hand();
	virtual ~Hand();
	//adds a card to the hand
	inline void Hand::Add(Card* pCard);

	//clears hand of all cards
	void Clear();

	//gets hand total value, treat ace as 1 or 11
	int GetTotal() const;
protected:
	vector<Card*> m_Cards;
};
Hand::Hand()
{
	m_Cards.reserve(7);
}
Hand::~Hand()
{
	Clear();
}
inline void Hand::Add(Card * pCard)
{
}
void Hand::Clear()
{
	vector<Card*>::iteraotr 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 card in hand, return 0
	if (m_Cards.empty())
	{
		return 0;
	}

	//if a first card has 0 vlaue
	if (m_Cards[0]->GetValue() == 0)
	{
		return 0;
	}

	//addup card value
	int total = 0;
	vector<Card*>::const_iterrator iter;
	for (iter = m_Cards.begin(); iter != m_Cards.end(); ++iter)
	{
		total += (*iter)->GetValue();
	}

	//determine if hadn 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 ac and total is low enough, treat ace as 11
	if (containsAce && total <= 11)
	{
		//add only 10
		total += 10;
	}
	return total;
}
#endif 
Card Class, also I input the Overloading operator <<() function in here, not sure if its the right way to do it

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#pragma once
#ifndef CARD_H_
#define CARD_H_
#include <iostream>
#include<string>
#include <vector>
#include <algorithm>
#include <ctime>

using namespace std;

class Card
{
public:
	enum rank { ACE = 1, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEN, KING };
	enum suit { CLUBS, DIAMONDS, HEARTS, SPADES };

	//overloading << operator so can send Card object to standard output freidn ostream& optn

	Card(rank r = ACE, suit s = SPADES, bool ifu = true);

	//return the value of a card 
	int GetValue() const;

	//flip a card
	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 card face down = 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);
}

//overloads << operator so card obejct can be sent out to cout
{
	const string RANKS[] = { "0", "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K" };
	const string SUITS][] = { "c", "d", "h", "s" };
	if (aCard.m_IsFaceUp)
	{
		os << RANKS[aCard.m_Rank] << SUITS[aCard.m_Suit];
	}
	else {
		os << "XX";
	}
	return os;
}

//overload << opt so genericPlaer obejct can be sent out to cout
{
	os << aGenericPlayer.m_Name << " :\t";
	vector<Card*>::const_iterator pCard;
	if (!aGenericPlayer.m_Cards.empty())
	{
		for (pCard = aGenericPlayer.m_Cards.begin();
			pCard != aGenericPlayer.m_Cards.end();
			++pCard)
		{
			os << *(*pCard) << "\t";
		}
		if (aGenericPlayer.GetTotal() != 0)
		{
			cout << "(" << aGenericPlayer.GetTotal() << ")";
		}
	}
	else
	{
		os << "<empty>";
	}
	return os;
}
#endif 
Hi, luiz5z.
My problem is I don’t know blackjack rules, so I’m just trying to guess what could be the problems, but I’m likely to be missing many points or say wrong things.

It seems you’ve written a lot of code before trying to compile it and that usually takes a lot of troubles along.
Just to make some examples:
In main() a semicolon is missing after char again = 'y'.

1
2
3
4
class Deck : public Hand
{
	Deck();
...

You constructor is private. That’s not forbidden (otherwise singletons couldn’t be possible), but makes it hard to make an instance of your class. The compiler immediately points it out.

1
2
3
inline void Hand::Add(Card * pCard)
{
}

You use this function in your code, but you havent’t implemented it yet. Again, the compiler never fails to find such errors.

1
2
3
4
class Game
{
...
	House m_House;

Where do you define “House”? The compiler asks it as soon as it meets that declaration.
(I suppose you meant to declare a ‘special’ Player named House, didn’t you?)

1
2
3
void Hand::Clear()
{
	vector<Card*>::iteraotr iter = m_Cards.begin();

«What’s an ‘iteraotr’?» the compiler asks.

Apart from what the compiler complains of, it seems you underestimate how splitting class into headers and sources can make the code more readable. Let me suggest you to try and see! It would also help you to include the right headers, as now by now they are a mess. What algorithm do you use in Game and what vector in Player? How can Game be aware of Deck if the former doesn’t include the latter?

Couldn’t it be better if Deck managed a (std::vector) bunch of Card(s) instead of inheriting from it? (Just an opinion)
And, well, I don’t know blackjack, but doesn’t it sound weird that a Deck is aware of a GenericPlayer and a Player isn’t aware of a Deck?

Iterators are great, but their syntax is prolix. What about substituting range-for for them?

Please note that function random_shuffle() was deprecated in C++14 and removed in C++17; the main reason is its implementations usually use std::rand(), which is frown upon in C++.
https://meetingcpp.com/blog/items/stdrandom_shuffle-is-deprecated.html

I wonder whether it wouldn’t be better to restart the code design writing down what every class responsibility should be, like for example:
- what a Game should manage?
- what a Hand should manage?
- what a Deck...
and so on.


- - -

What’s above is my real advice: restart from scratch.
Anyway, not so look too harsh, I’ve spent some time making your code a bit more readable. Let me be clear: it doesn’t mean it’s better, but I succeeded in cutting down the errors to no more than 7; however, a reduced number of errors from the compiler doesn’t mean the code follows a good logic (to be sincere: I’m not sure I understood your logic).

GenericPlayer.hpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#ifndef GENERICPLAYER_H_
#define GENERICPLAYER_H_

#include "Hand.hpp"
#include <iostream>
#include <string>
#include <vector>

class GenericPlayer : public Hand
{
public:
    GenericPlayer(const std::string& name = "");
    virtual ~GenericPlayer();

    // indicate whther or not player wan to keep hitting
    virtual bool IsHitting() const = 0;

    // return whether generic player has busted - has a total greater than 21
    bool IsBusted() const;

    // announces that the player busts
    void Bust() const;

protected:
    std::string m_Name;

    friend std::ostream& operator<<(std::ostream& os, const GenericPlayer& ap)
    {
        os << ap.m_Name << ":\t";
        if (!ap.m_Cards.empty()) {
            for(const auto& c : ap.m_Cards) { os << c << "\t"; }
            if (ap.GetTotal() != 0) { std::cout << "(" << ap.GetTotal() << ")"; }
        } else {
            os << "<empty>";
        }
        return os;
    }
};

#endif // GENERICPLAYER_H_ 


GenericPlayer.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "GenericPlayer.hpp"
#include <iostream>
#include <string>

/*
 */
GenericPlayer::GenericPlayer(const std::string& name) : m_Name(name) {}


/*
 */
GenericPlayer::~GenericPlayer() {}


/*
 */
bool GenericPlayer::IsBusted() const { return GetTotal() > 21; }


/*
 */
void GenericPlayer::Bust() const { std::cout << m_Name << " busts.\n"; }


Player.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#ifndef PLAYER_H_
#define PLAYER_H_

#include "GenericPlayer.hpp"

class Player : public GenericPlayer
{
public:
    Player(const std::string& name = "");
    virtual ~Player();

    // return whter or not the player wants another hit
    virtual bool IsHitting() const;

    // announces that the plaer wins
    void Win() const;
    
    // announces that the player loses
    void Lose() const;

    // announces that the player pushes
    void Push() const;
};

#endif // PLAYER_H_ 


Player.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include "Player.hpp"
#include <iostream>
#include <string>

/*
 */
Player::Player(const std::string& name): GenericPlayer(name) {}


/*
 */
bool Player::IsHitting() const
{
    std::cout << m_Name << ", do you want a hit? (Y/N): ";
    char response;
    std::cin >> response;
    return (response == 'y' || response == 'Y');
}


/*
 */
void Player::Win() const { /* TODO: to be done!!  */ }


/*
 */
void Player::Lose() const { std::cout << m_Name << " loses.\n"; }


/*
 */
void Player::Push() const { std::cout << m_Name << " pushes.\n"; }


Card.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#ifndef CARD_H_
#define CARD_H_

#include <algorithm>
#include <ctime>
#include <iostream>
#include <string>
#include <vector>

class Card
{
public:
    enum rank { ACE = 1, TWO,   THREE, FOUR, FIVE,
                SIX,     SEVEN, EIGHT, NINE, TEN,
                JACK,    QUEN,  KING               };
    enum suit { CLUBS, DIAMONDS, HEARTS, SPADES };

    Card(rank r = ACE, suit s = SPADES, bool ifu = true);

    // return the value of a card 
    int GetValue() const;

    // flip a card
    void Flip();

private:
    rank m_Rank;
    suit m_Suit;
    bool m_IsFaceUp;

    friend std::ostream& operator<<(std::ostream& os, const Card& aCard)
    {
        const std::string RANKS[] = {  "0", "A", "2", "3", "4",
                                       "5", "6", "7", "8", "9",
                                      "10", "J", "Q", "K"       };
        const std::string SUITS[] = { "c", "d", "h", "s" };

        if (aCard.m_IsFaceUp) { os << RANKS[aCard.m_Rank] << SUITS[aCard.m_Suit]; }
        else                  { os << "XX"; }
        return os;
    }
};

#endif // CARD_H_ 


Card.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include "Card.hpp"


/*
 */
Card::Card(rank r, suit s, bool ifu) : m_Rank(r), m_Suit(s), m_IsFaceUp(ifu) {}


/*
 */
int Card::GetValue() const
{
    // value is the Rank of the card; for face cards is 10
    if(m_IsFaceUp) { return m_Rank > 10 ? 10 : m_Rank; }
    return 0;                       // if a is card face down, its value is 0
}


/*
 */
void Card::Flip() { m_IsFaceUp = !m_IsFaceUp; }


Hand.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#ifndef HAND_H_
#define HAND_H_

#include "Card.hpp"
#include <vector>

class Hand
{
public:
    static constexpr unsigned CARD_IN_HAND { 7 };
    Hand();
    virtual ~Hand();
    // adds a card to the hand
    inline void Add(Card* pCard);

    // clears hand of all cards
    void Clear();

    // gets hand total value, treat ace as 1 or 11
    int GetTotal() const;
protected:
    std::vector<Card*> m_Cards;
};

#endif // HAND_H_ 

Hand.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include "Hand.hpp"
#include <string>
#include <vector>


/*
 */
Hand::Hand() { m_Cards.reserve(CARD_IN_HAND); }


/*
 */
Hand::~Hand() { Clear(); }


/*
 */
inline void Hand::Add(Card * pCard) { /* TODO: to be done!! */ }


/*
 */
void Hand::Clear()
{
    for (auto* c : m_Cards) {
        delete c;
        c = nullptr;
    }
    // clear std::vector of pointers
    m_Cards.clear();
}


/*
 */
int Hand::GetTotal() const
{
    // if no card in hand, return 0
    if (m_Cards.empty()) { return 0; }

    // if a first card has value 0
    if (m_Cards.at(0)->GetValue() == 0) { return 0; }

    // add up card value
    int total = 0;
    for(const auto* c : m_Cards) { total += c->GetValue(); }

    // determine if hand contains an ace
    bool containsAce = false;
    for(const auto* c : m_Cards) {
        if (c->GetValue() == Card::rank::ACE) { containsAce = true; }
    }

    // if hand contains ac and total is low enough, treat ace as 11
    if (containsAce && total <= 11) { total += 10; }
    return total;
}


Deck.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#ifndef DECK_H_
#define DECK_H_

#include "Hand.hpp"
#include "GenericPlayer.hpp"

class Deck : public Hand
{
public:
    static constexpr unsigned DECK_SIZE { 52 };
    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);

    // give additional cards to a generic plauer
    void AdditionalCards(GenericPlayer& ap);
};

#endif //  DECK_H_ 


Deck.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include "Deck.hpp"
#include "Card.hpp"
#include <chrono>
#include <algorithm>
#include <iostream>
#include <random>
#include <string>
#include <vector>


/*
 */
Deck::Deck()
{
    m_Cards.reserve(DECK_SIZE);
    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)));
        }
    }
}


/*
 */
// Beware!! random_shuffle() was deprecated in C++14 and removed in C++17!
void Deck::Shuffle() {
    std::mt19937 eng { static_cast<unsigned>(
                        std::chrono::high_resolution_clock::now()
                        .time_since_epoch()
                        .count() ) };
    shuffle(m_Cards.begin(), m_Cards.end(), eng);
}


/*
 */
void Deck::Deal(Hand& aHand)
{
    if (!m_Cards.empty()) {
        aHand.Add(m_Cards.back());
        m_Cards.pop_back();
    } else {
        std::cout << "Out of cards. Unable to deal. ";
    }
}


/*
 */
void Deck::AdditionalCards(GenericPlayer& ap)
{
    std::cout << '\n';
    //continue to deal
    while (!(ap.IsBusted()) && ap.IsHitting()) {
        Deal(ap);
        std::cout << ap << '\n';
        if (ap.IsBusted()) { ap.Bust(); }
    }
}


Game.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef GAME_H_
#define GAME_H_

#include "Deck.hpp"
#include "Hand.hpp"
#include "Player.hpp"
#include <vector>

class Game
{
public:
    Game(const std::vector<std::string>& names);
    ~Game();

    // plays the game of blackjack
    void Play();
private:
    Deck m_Deck;
    House m_House;
    std::vector<Player> m_Players;
};

#endif // GAME_H_ 


Game.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include "Game.hpp"
#include <vector>

/*
 */
Game::Game(const std::vector<std::string>& names)
{
    // create a std::vector of player from a std::vector of names
    for(const auto& s : names) { m_Players.push_back(Player(s)); }

    // seed the random number generator
    srand(static_cast<unsigned int>(time(0)));

    m_Deck.Populate();
    m_Deck.Shuffle();
}

/*
 */
Game::~Game() {}

/*
 */
void Game::Play()
{
    // deal initial 2 cards to everyone
    for (int i = 0; i < 2; ++i) {
        for(auto& a : m_Players) { m_Deck.Deal(a); }
        m_Deck.Deal(m_House);
    }

    // hide house's first card
    m_House.FlipFirstCard();

    // dipslay everyone's hand
    for(const auto& a : m_Players) { std::cout << a << '\n'; }
    std::cout << m_House << '\n';

    //  deal additional cards to players
    for(auto& a : m_Players) { m_Deck.AdditionalCards(a); }

    // reveal house's first card
    m_house.FlipFirstCard();
    std::cout << '\n' << m_House;

    // deal additional cards to house
    m_Deck.AdditionalCards(m_House);

    if (m_House.IsBusted()) {
        // everyone still playing win
        for(auto& a : m_Players) { if ( !a.IsBusted() ) { a.Win(); } }
    } else {
        // compare each player still playing to house
        for(auto& a : m_Players) {
            if      ( !a.IsBusted() )                   { a.Win(); }
            else if (a.GetTotal() < m_House.GetTotal()) { a.Lose(); }
            else                                        { a.Push(); }
        }
    }

    // remove everyone cards
    for(auto& a : m_Players) { a.Clear(); }
    m_House.Clear();
}


main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include "Game.hpp"
#include <iostream>
#include <string>
#include <vector>

//function prototypes
std::vector<std::string> getPlNames();

int main()
{
    std::cout << "\t\tWelcome to blackjack!\n\n";
    std::vector<std::string> names = getPlNames();
    std::cout << '\n';
    //the game loop
    Game aGame(names);
    char again = 'y';
    while(again !='n' && again!='N')
    {
        aGame.Play();
        std::cout << "\n Do you want to play again? (Y/N):\n";
        std::cin >> again;
    }
    return 0;
}


/*
 */
std::vector<std::string> getPlNames()
{
    int numPlayers = 0;
    while (numPlayers < 1 || numPlayers > 7)
    {
        std::cout << "How many players? (1-7):\n";
        std::cin >> numPlayers;
    }
    std::vector<std::string> names(numPlayers);
    std::string name;
    for (int i = 0; i < numPlayers; ++i)
    {
        std::cout << "Enter name for player " << i + 1 << ": ";
        std::cin >> name;
        names.at(i) = name;
    }
    return names;
}

I add House.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include "House.h"
#include "Card.h"
#include <iostream>
#include <string>

//
House::House(const std::string& name) : GenericPlayer(name) {}


// Revel House First Card
bool House::FlipFirstCard() const
{

}


// If House WIN
void House::Win() const { std::cout << m_Name << " You Lose! \n"; }


// If house Lose
void House::Lose() const { std::cout << m_Name << " You win!.\n"; }


//Push
void House::Push() const { std::cout << m_Name << " pushes.\n"; }


and House.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#pragma once
#ifndef HOUSE_H_
#define HOUSE_H_

#include "GenericPlayer.h"

class House : public GenericPlayer
{
public:
	House(const std::string& name = "");
	virtual ~House();

	// return whether or not the player wants another hit
	virtual bool FlipFirstCard() 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;
};

#endif // HOUSE_H_ 


still having a problem with initializing the house.h with FlipFirstCard(), I'm so lost in this one
Topic archived. No new replies allowed.