# Thread: Making a Blackjack game..

1. Well, it doesn't make much difference once the code is compiled. But reading code like:
Code:
enum  { NoSuite, Clubs, Diamonds, Hearts, Spades } Suites;
enum  { NoValue, Two=2, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Knight, Queen, King, Ace } Value;

...
if (suite == Hearts && value == King) ...
...
is much easier than when they are numerical values. This is the purpose of enum declarations.

--
Mats

2. You can even set up the enum so that you can use the enumerated names, or you can treat the enum value as an int and use that to index the lookup-table-array or whatever. It can be sort of a bad programming practise (and certainly difficult to add new values -- not that that will ever happen with a deck of cards), but you get the best of both worlds. Something like this:
Code:
enum value {
value_none = -1,
value_two,
value_three,
value_four,
/* ... */
value_king
values
};

3. yeah it'd be alot simpler than just creating a seperate case/if statement with an enum to do something as simple as output the card values and suit.

4. Cards can be represented numerically. Divide the card number by the number of cards in a suite to get the suite number. Turn the suite number into a string using some of the suggested approaches.

You can also do a modulo operation on the number of cards in the deck to arrive at the suite. This suite value can then be used as an index into an array of strings to extract the actual suite name.

5. I've created lookup tables for outputting the card suits and values onto the screen.

I need some help creating the function that actually looks up the card strings by value though, for some reason I can't pass Card as a parameter of the ReadCards(Card) function.

Here's the dealer class so far.
Code:
#include <stdio.h>
#include <stdlib.h>
#include "Deck.h"

using namespace std;

class Dealer
{
public:

Dealer()
{
InitLookups();
}
void ShuffleDeck()
{
int random = 0;
int loopvar = 0;
for (loopvar; loopvar < 52; loopvar++)
{
random = rand() % 52;
std::swap(BlackJackDeck.Cards[loopvar], BlackJackDeck.Cards[random]);
}
}

{
//look through the tables using the
//card value and suit as an index...
}

// Creates Lookup tables for outputting card suits and values
void InitLookups()
{
string Suit;

string Value;
}
private:

{
SuitStrings.push_back(Suit);
}

{
ValueStrings.push_back(Value);
}

Deck BlackJackDeck;

protected:  //string lookups
std::vector<string> SuitStrings;
std::vector<string> ValueStrings;
};
And here is the deck code
Code:
// This header file declares the deck class and all of its functions,
// as well as the card structure.

#include <vector>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <cassert>

class Deck
{
public:

struct Card
{
int suit;
int value;
};

Deck()
{
int x = 0;
int y = 0;
for (y = 0; y < 4;  y++)
{

for (x = 0; x < 13; x++)
{
Card C;
C.suit = y;
C.value = x;
Cards.push_back(C);
}
}
assert(Cards.size() == 52);
}

private:
friend class Dealer;
std::vector<Card> Cards;
};
I need to figure out how to pass suits and values to the read cards function...

6. Here is my attempt.
I made a few functions in the deck class to return the value and suit of the cards.
And then I made the read cards function take an int for value and suit.
Code:
{
cout << ValueStrings[value].c_str() << " of "
<< SuitStrings[suit].c_str();
//card value and suit as an index...
}
Simple bwahaha.

I'm gonna rewrite it so that it constructs a new string that will read value of suit that I can return through the function.

7. Your shuffle code is wrong. It will not produce an even distribution (even if rand() was perfectly random).

I would use random_shuffle.

If you want to learn how to create a proper shuffling algorithm, it's not much different. You have to reduce the range of your random number each time, so instead of rand() &#37; 52 you would use loopvar in some capacity.

8. When I made a blackjack game the PlayersHand class had a draw() method, which would call the draw() method of each Card object the player holds. In this spirit I feel that your cards might "know" how to "draw" themselves, for example by containing static look-up tables.

The Deck object would have a method for reporting how many undrawn cards are left, so that the caller can decide if the Deck's reshuffle() method needs to be called (and the Deck would reshuffle automatically if it runs out of cards while the deal_card() method is called to avoid trouble, but you might assert instead).

9. I figure the dealer's class has ownership of the deck class, and the dealer will be doing the one actually drawing cards.

I think both the dealers and the players actions will be a result of the Game class, it will control the actions of both the dealer and the player. I hope that maybe I can encapsulate the game class enough so that a little bit of code can create a whole new game without changing the dealer/player class.

The player might communicate to the game that he would like to draw another card, and then the game would tell the dealer to deal another card.

Or maybe it would go player->dealer->game. Not too sure on this one.
Actually I'm pretty sure it will always run Game->Dealer->Player. This will be the main loop of the game state.

I'd first have to figure out some basic functions of a card game. These functions will manipulate how the dealer and player classes act. The dealer really only does two things, shuffle cards and deal them. The player can only do one thing in the case of blackjack, and that is the option to draw more cards. Also I guess the player can decide if an Ace card will be worth 1 or 11.

So perhaps there will be a few methods that send messages to the dealer to hand out cards. In some cases the dealer will have a hand as well, perhaps in a game of texas holdem with 1 human and then computer AI. The dealer needs to keep track of the number of cards in the deck. It will be told by the game when to shuffle.

10. I'd first have to figure out some basic functions of a card game. These functions will manipulate how the dealer and player classes act. The dealer really only does two things, shuffle cards and deal them. The player can only do one thing in the case of blackjack, and that is the option to draw more cards. Also I guess the player can decide if an Ace card will be worth 1 or 11.
I found it simpler if the game handed cards out to both the dealer and the player (so player's cards don't move strictly through the dealer object), something like Player::takeCard(deck::dealCard()).

I don't think a dealer should know how to shuffle cards (that is, the implementation details), because it would actually be the Deck who encapsulates all the data related to shuffling. The dealer (or Game) might call Deck::shuffle and the deck would get shuffled.

In Blackjack the value of an ace should be determined by the logic of the game: it is 11 unless the player goes over 21. In my game I had an object to represent cards held by a player, and this object could calculate and report the sum of the cards.

11. game.h
Code:
#include "Dealer.h"
using namespace std;

class Game
{
public:
Dealer dealer;
Player player;
void playgame()
{
int gameloop = 1;
InitValues();
dealer.ShuffleDeck();
dealer.Deal(2, dealer.Hand);
dealer.Deal(1, player.Hand);
while(gameloop != 0)
{
gameloop = BlackJack(dealer.Turn(player));
}

}

int BlackJack(int option)
{
if (option == 1)	// check player hand, over 21?
{
if (Hand(player.Hand) > 21)
{
cout << "You Lose!!!!" << endl;
return 0;
}
else { return 1; }
}
if (option == 2)	// compare hands and declare winner
{
if(Hand(player.Hand) > Hand(dealer.Hand))
{
cout << "You win!!!!" << endl;
return 1;
}
else { return 0; }
}
if (option == 3)	// player folds, remove them from game.
{
cout << "You Lose!!!" << endl;
return 0;
}
return 1;
}

int Hand(vector<Card> & hand)
{
sum = 0;
for (int loop = 0; loop < hand.size(); loop++)
{
sum += values[player.Hand[loop].Value];
}
return sum;
}
void InitValues()
{
values.push_back(2);
values.push_back(3);
values.push_back(4);
values.push_back(5);
values.push_back(6);
values.push_back(7);
values.push_back(8);
values.push_back(9);
values.push_back(10);
values.push_back(10);
values.push_back(10);
values.push_back(10);
values.push_back(11);
}
int sum;
vector<int> values;
};
Here is the game class, pretty much a rough outline, still some bugs... When I hit the second option, and count my cards, i see clearly in the program output (and debug mode) that my cards are either higher or lower than the dealers, but nothing happens? I should either lose or win, no matter what, but it doesn't do anything... something is fudging up...

Anyways here's the rest of the code:
player.h
Code:
using namespace std;

class Player
{
int GetInput()
{
int choice;
cout << "What would you like to do?" << endl;
cout << "1: Hit Me" << endl;
cout << "2: Stay"   << endl;
cout << "3: Fold"   << endl;
cin  >> choice;
return choice;
}

friend class Dealer;
friend class Game;
vector<Card> Hand;
};
dealer.h
Code:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include "Deck.h"
#include "Player.h"

using namespace std;

class Dealer
{
public:

Dealer()
{
InitLookups();
}
void ShuffleDeck()
{
random_shuffle(deck.cards.begin(), deck.cards.end());
}

int Turn(Player & player)
{
if (player.GetInput() == 1)
{
Deal(1, player.Hand);
return 1; // is player's hand > 21?
}
if (player.GetInput() == 2)
{
return 2; //run game formulas
}
if (player.GetInput() == 3)
{

return 3; //player folded, remove player from game.
}
return 0;
}

void Deal(int howmanycards, vector<Card> & hand)
{
for (int loop = 0; loop != howmanycards; loop++)
{
hand.push_back(deck.cards.back());
deck.cards.pop_back();
}
}

{
cout << valuelookup[value].c_str() << " of "
<< suitlookup[suit].c_str() << "   ";
//card value and suit as an index...
}

// Creates Lookup tables for outputting card suits and values
void InitLookups()
{
string suit;

string value;
}
private:

{
suitlookup.push_back(suit);
}

{
valuelookup.push_back(value);
}

private:  //string lookups
vector<string> suitlookup;
vector<string> valuelookup;
vector<Card> Hand;
Deck deck;
friend class Game;
};
sorry i suck at documentation bahahah

12. Code:
int Turn(Player & player)
{
if (player.GetInput() == 1)
{
Deal(1, player.Hand);
return 1; // is player's hand > 21?
}
if (player.GetInput() == 2)
{
return 2; //run game formulas
}
if (player.GetInput() == 3)
{

return 3; //player folded, remove player from game.
}
return 0;
}
It seems that during each turn the player gets to make 3 choices. For a menu a switch (-like structure) is suitable:
Code:
switch (player.GetInput()) {
case 1: ...
Edit: However, this function does nothing else than

Code:
int Turn( Player& player)
{
int result = player.GetInput();
if (result == 1) {
Deal(1, player.hand);
}
return result;
}
Code:
if (option == 2)	// compare hands and declare winner
{
if(Hand(player.Hand) > Hand(dealer.Hand))
{
cout << "You win!!!!" << endl;
return 1;
}
else { return 0; }
Here it looks like the game continues if player wins (shouldn't it return 0 always, because the game is definately over here?

13. Okay, everything works except for one strange bug. Whenever I hit option 2 without first drawing a card I get a debug assertion error "vector subscript out of range." If I draw a card whether or not I win or lose it gives me a win/lose case. But when I don't draw a cad it breaks.

Any ideas?
Code:
#include "Dealer.h"
using namespace std;

class Game
{
public:
Dealer dealer;
Player player;
void playgame()
{
int gameloop = 1;
InitValues();
dealer.ShuffleDeck();
dealer.Deal(2, dealer.Hand);
dealer.Deal(1, player.Hand);
while(gameloop != 0)
{
gameloop = BlackJack(dealer.Turn(player));
}

}

int BlackJack(int option)
{
if (option == 1)	// check player hand, over 21?
{
if (Hand(player.Hand) > 21)
{
cout << "You Lose!!!!" << endl;
return 0;
}
else { return 1; }
}
if (option == 2)	// compare hands and declare winner
{
if(Hand(player.Hand) > Hand(dealer.Hand))
{
cout << "You win\n!!!!";
return 0;
}
else { cout << " You Lose\n!!!"; return 0; }
}
if (option == 3)	// player folds, remove them from game.
{
cout << "You Lose!!!\n";
return 0;
}
else{ return 0; }

}

int Hand(vector<Card> & hand)
{
sum = 0; int loop = 0;
for (loop; loop < hand.size(); loop++)
{
sum += values[player.Hand[loop].Value];
}
return sum;
}
void InitValues()
{
values.push_back(2);
values.push_back(3);
values.push_back(4);
values.push_back(5);
values.push_back(6);
values.push_back(7);
values.push_back(8);
values.push_back(9);
values.push_back(10);
values.push_back(10);
values.push_back(10);
values.push_back(10);
values.push_back(11);
}
int sum;
vector<int> values;
};
Code:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include "Deck.h"
#include "Player.h"

using namespace std;

class Dealer
{
public:

Dealer()
{
InitLookups();
}
void ShuffleDeck()
{
random_shuffle(deck.cards.begin(), deck.cards.end());
}

int Turn(Player & player)
{
int result = player.GetInput();
if (result == 1)
{
Deal(1, player.Hand);
return 1; // is player's hand > 21?
}
if (result == 2)
{
return 2; //compare cards declare winner
}
if (result == 3)
{
return 3; //player folded, remove player from game.
}
result = player.GetInput();
}

void Deal(int howmanycards, vector<Card> & hand)
{
for (int loop = 0; loop != howmanycards; loop++)
{
hand.push_back(deck.cards.back());
deck.cards.pop_back();
}
}

{
v = value;
s = suit;
cout << valuelookup[value].c_str() << " of "
<< suitlookup[suit].c_str() << "   ";
//card value and suit as an index...
}

// Creates Lookup tables for outputting card suits and values
void InitLookups()
{
string suit;

string value;
}
private:

{
suitlookup.push_back(suit);
}

{
valuelookup.push_back(value);
}
int v; int s;
//string lookups
vector<string> suitlookup;
vector<string> valuelookup;
vector<Card> Hand;
Deck deck;
friend class Game;
};
Code:
#include "Dealer.h"
using namespace std;

class Game
{
public:
Dealer dealer;
Player player;
void playgame()
{
int gameloop = 1;
InitValues();
dealer.ShuffleDeck();
dealer.Deal(2, dealer.Hand);
dealer.Deal(1, player.Hand);
while(gameloop != 0)
{
gameloop = BlackJack(dealer.Turn(player));
}

}

int BlackJack(int option)
{
if (option == 1)	// check player hand, over 21?
{
if (Hand(player.Hand) > 21)
{
cout << "You Lose!!!!" << endl;
return 0;
}
else { return 1; }
}
if (option == 2)	// compare hands and declare winner
{
if(Hand(player.Hand) > Hand(dealer.Hand))
{
cout << "You win\n!!!!";
return 0;
}
else { cout << " You Lose\n!!!"; return 0; }
}
if (option == 3)	// player folds, remove them from game.
{
cout << "You Lose!!!\n";
return 0;
}
else{ return 0; }

}

int Hand(vector<Card> & hand)
{
sum = 0; int loop = 0;
for (loop; loop < hand.size(); loop++)
{
sum += values[player.Hand[loop].Value];
}
return sum;
}
void InitValues()
{
values.push_back(2);
values.push_back(3);
values.push_back(4);
values.push_back(5);
values.push_back(6);
values.push_back(7);
values.push_back(8);
values.push_back(9);
values.push_back(10);
values.push_back(10);
values.push_back(10);
values.push_back(10);
values.push_back(11);
}
int sum;
vector<int> values;
};
Code:
using namespace std;

class Player
{
int GetInput()
{
int choice = 0;
cout << "What would you like to do?" << endl;
cout << "1: Hit Me" << endl;
cout << "2: Stay"   << endl;
cout << "3: Fold"   << endl;
cin  >> choice;
return choice;
}

friend class Dealer;
friend class Game;
vector<Card> Hand;
};
Also to note, when I set a breakpoint for debugging before I call the turn function it says

"failed to create breakpoint"
unable to parse function int Turn(player)

14. Code:
if(Hand(player.Hand) > Hand(dealer.Hand))

int Hand(vector<Card> & hand)
{
sum = 0; int loop = 0;
for (loop; loop < hand.size(); loop++)
{
sum += values[player.Hand[loop].Value];
}
return sum;
}
I cannot follow this function: it uses the argument to decide how many times to loop, and then checks Player's hand anyway?

15. okay I fixed that last problem and everything works fine, now im working on the ouput..

Code:
class Dealer : public Player
{
public:

Dealer()
{
playerid = 0;
InitLookups();
}
void ShuffleDeck()
{
random_shuffle(deck.cards.begin(), deck.cards.end());
}

int Turn(Human_Player & player)
{
int result = player.GetInput();
if (result == 1)
{
Deal(1, player);
return 1; // is player's hand > 21?
}
if (result == 2)
{
return 2; //compare cards declare winner
}
if (result == 3)
{
return 3; //player folded, remove player from game.
}
result = player.GetInput();
}

void Deal(int howmanycards, Player & player)
{
if {player.playerid == 0)
{
for (int loop = 0; loop != howmanycards; loop++)
{
player.hand.push_back(deck.cards.back());
if (loop == 2)
{
cout << "Card" << endl;
deck.cards.pop_back();
}
else
{
deck.cards.pop_back();
}
}
}
else
{
for (int loop = 0; loop != howmanycards; loop++)
{
hand.push_back(deck.cards.back());
deck.cards.pop_back();
}
}
}

void ReadCards(int value,int suit, int playerid)
{
cout << valuelookup[value].c_str() << " of "
<< suitlookup[suit].c_str() << endl;
//card value and suit as an index...
}

// Creates Lookup tables for outputting card suits and values
void InitLookups()
{
string suit;

string value;
}
private:

{
suitlookup.push_back(suit);
}

{
valuelookup.push_back(value);
}
//string lookups
vector<string> suitlookup;
vector<string> valuelookup;
vector<Card> hand;
Deck deck;
friend class Game;
};
I'm getting an unexpected end of file for '{' at dealer.h..

Code:
------ Build started: Project: Blackjack, Configuration: Debug Win32 ------
Compiling...
Blackjack.cpp
c:\documents and settings\jon c\desktop\blackjack\blackjack\game.h(5) : error C2059: syntax error : 'namespace'
c:\documents and settings\jon c\desktop\blackjack\blackjack\game.h(5) : error C2238: unexpected token(s) preceding ';'
c:\documents and settings\jon c\desktop\blackjack\blackjack\game.h(10) : error C2079: 'Dealer::Game::dealer' uses undefined class 'Dealer'
c:\documents and settings\jon c\desktop\blackjack\blackjack\blackjack.cpp(16) : fatal error C1075: end of file found before the left brace '{' at 'c:\documents and settings\jon c\desktop\blackjack\blackjack\dealer.h(13)' was matched
Build log was saved at "file://c:\Documents and Settings\Jon C\Desktop\Blackjack\Blackjack\Debug\BuildLog.htm"
Blackjack - 4 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
as far as I can tell my if's and else's brackets are matched correctly, any ideas?