Here is it... the final program
Thanks to everyone who helped out
The biggest problems with writing this program were:
1) declaring new objects inside the constructor (illegal in c++)
2) istreamstring will only accept variable &addresses. It took me awhile to figure this out. I tried to stream using variable itself.. but it never worked.. I thought it looked like the example in the FAQ.. but as soon as I put in the variable address.. bingo! worked like a charm.
so kids.. save yourself a lot of trouble.. and learn from my mistakes.
Feel free to compile and play me' game also, please continue to critique my code.. because your feedback will help me and others become better programmers
Code:
#include<algorithm> //Provides swap()
#include<iostream> //Provides 'cin', 'cout', & 'NULL'
#include<sstream> //Provides 'string to int' conversion
#include<cstdlib> //Provides system(), rand() & srand()
#include<string> //Provies 'string' type qualifier
#include<cctype> //Provides toupper()
#include<conio.h> //Provides getch() & clrscr()
using namespace std;
class blackjack
{
public:
//CONSTRUCTOR
blackjack();
//MUTATORS
void shuffle_deck();
void the_dealer(char);
void winner_determination(char);
//ACCESSORS
void display_hand();
//CONSTANTS
bool is_bust(int) const;
//FRIENDS
friend int card_value(string);
private:
string deck[4][13];
string player_hand[10];
string dealer_hand[10];
string face_value;
string suite;
string card;
int counter_1D;
int counter_2D;
int ph_counter;
int dh_counter;
int playerhand_value;
int dealerhand_value;
};
//NONMEMBER FUNCTION PROTOTYPES
void seed_random();
char get_user_command();
void exit_message();
int main()
{
seed_random();
blackjack card;
char choice = 'x';
clrscr();
do
{
card.shuffle_deck();
card.display_hand();
choice = toupper(get_user_command());
card.the_dealer(choice);
clrscr();
card.display_hand();
if (choice != 'Q')
card.winner_determination(choice);
clrscr();
}while (choice != 'Q');
exit_message();
return 0;
}//end MAIN()
////////////////////////////////////////////
/////////// FUNCTION DEFINITIONS ///////////
////////////////////////////////////////////
blackjack::blackjack()
{
//Initialize card counter member variables.
counter_1D = 0;
counter_2D = 0;
ph_counter = 0;
dh_counter = 0;
playerhand_value = 0;
dealerhand_value = 0;
//Initialize player & dealer hand string arrays
for(int h = 0; h < 10; h++)
{
player_hand[h] = "Test";
dealer_hand[h] = "Test";
}
//Initialize deck[][]
//create a deck of cards, 4 suits, 13 cards per suit (2 thru Ace)
//string suite, face_value, card;
for (int i = 0; i < 4; i++) //Use the outter FOR loop to determine the suite of deck[suite][face_value]
{
switch(i)
{
case 0: suite = "Hearts";
break;
case 1: suite = "Diamonds";
break;
case 2: suite = "Clubs";
break;
case 3: suite = "Spades";
break;
default: cout << "\n\nsuite loop overflow\n";
}//end switch
for (int j = 0; j < 13; j++) //The Inner FOR loop will assign card face values
{
switch(j)
{
case 0: face_value = "2";
break;
case 1: face_value = "3";
break;
case 2: face_value = "4";
break;
case 3: face_value = "5";
break;
case 4: face_value = "6";
break;
case 5: face_value = "7";
break;
case 6: face_value = "8";
break;
case 7: face_value = "9";
break;
case 8: face_value = "10";
break;
case 9: face_value = "Jack";
break;
case 10: face_value = "Queen";
break;
case 11: face_value = "King";
break;
case 12: face_value = "Ace";
break;
default: cout << "\n\nface_value loop overflow\n";
}//end switch
//This block will create a "card" to be assigned to the deck
card = face_value;
card += " of ";
card += suite;
deck[ i][j] = card;
}//end INNER FOR
}//end OUTTER FOR
}
void blackjack::shuffle_deck()
{
for( int y = 0; y < 4; y++)
for (int z = 0; z < 13; z++)
swap(deck[y][z], deck[rand()%4][rand()%13]);
}
void blackjack::display_hand()
{
cout << endl << endl << " Dealer's Hand: " << dealerhand_value << "\n\n ";
for (int i = 0; i < dh_counter; i++)
cout << dealer_hand[ i] << "\t";
cout << endl << endl << endl;
cout <<"\n\n Your Hand: " << playerhand_value << "\n\n ";
for (int j = 0; j < ph_counter; j++)
cout << player_hand[j] << "\t";
cout << endl << endl << endl;
}
char get_user_command()
{
char command = 'x';
cout << "\n\n 'H' to HIT"
<< "\n 'S' to STAY"
<< "\n 'Q' to QUIT\n\n";
command = getch();
return command;
}
//seeds the random number generator to eliminate repitition
void seed_random()
{
time_t seed = time(NULL);
srand(seed);
}
void blackjack::the_dealer(char choice)
{
if (counter_2D >= 13) //This will advance deck to the second 'row' if row[0] has been used
{
++counter_1D;
counter_2D = 0;
}
else if (choice == 'H')
{
string card = deck[counter_1D][counter_2D++]; //Pick a card starting from the top of the deck (deck[0][0])
player_hand[ph_counter++] = card; //Add card 'string' to players hand
playerhand_value += card_value(card); //Add the cards numerical value to the players hand
}
else if (choice == 'S')
{
do
{
string card = deck[counter_1D][counter_2D++];
dealer_hand[dh_counter++] = card;
dealerhand_value += card_value(card);
}while (dealerhand_value < playerhand_value);
}
}
bool blackjack::is_bust(int test) const
{
return (test > 21);
}
void blackjack::winner_determination(char choice)
{
//Lose Logic is based on 3 situations: 1) you bust 2)you 'stayed' and lost 3) dealer has 21
//This evaluation for 'Losing' is made first, due to "dealerhand_value == 21"
if (is_bust(playerhand_value) || ((playerhand_value <= dealerhand_value) && (dealerhand_value <= 21)
&& (choice == 'S')) || (dealerhand_value == 21))
{
cout << "\n\n\n You Loooooose !!!!\n\n"
<< "Press [Enter] to continue ";
cin.get();
//reset everything in preperation for the next hand
playerhand_value = 0;
dealerhand_value = 0;
ph_counter = 0;
dh_counter = 0;
}
else if (is_bust(dealerhand_value) || ((playerhand_value > dealerhand_value) && (playerhand_value < 21)
&& (choice == 'S') && (dealerhand_value != 0)) || (playerhand_value == 21))
{
cout << "\n\n\n You Weeeeeeen !!!!\n\n"
<< "Press [Enter] to continue ";
cin.get();
//reset everything in preperation for the next hand
playerhand_value = 0;
dealerhand_value = 0;
ph_counter = 0;
dh_counter = 0;
}
}
//Converts the first character of a playing card from 'string' to 'int' so numeric comparisons can be made.
//Example: string '2 of Diamonds' will be converted to integer '2'
//istringstream can only accept the &address of the character to be streamed to integer
int card_value(string card)
{
int result = 0;
char *card_ptr;
card_ptr = &card[0]; //string class variables can be treated like arrays
istringstream myStream(card_ptr); //create a 'myStream' object of class istringstream
if (myStream >> result) //String to Integer converstion (works only for numeric face values)
return result; //return an integer value 2 thru 10
else
{
if (*card_ptr != 'A')
return 10; //"J", "Q", and "K" will return a face value of 10
else
return 11; //"A" will always return a value of 11
}
}
void exit_message()
{
cout << "\nProgram written in C++ by David R. Weirich "
<< "\nThanks to everyone at www.cprogramming.com"
<< "\[email protected]"
<< "\n\nThank you for playing.\n\n";
}
Program Assumptions: Ace will always equal 11
Program Difficiencies: Program does not allow the user to place bets, split, double down, or buy insurance.
Also, card output is affected by 'tab' discontinuities.
All system("pause" ) and system("cls") commands have been replaced by better alternatives per forum FAQ.