Blackjack (21) Game

• 12-19-2001
Rabidpunk
Blackjack (21) Game
Black Jack (21) Game

Hey everyone, I love the site/forum. I just started doing C++ after learning C a long long long time ago (back when Communists had more of a chance of running the country than Democrats) and now i'm back into it. The first thing i'm trying to do is make a blackjack game. I've yet to try the FAQ for the random number generator, but i'll suppose it works.

The basic idea of the program is to make a game of 21. Two variables, your hand and the dealers. You can hit or stay. This is the most basic version. Without splitting, suits are not needed. So I want to generate two begining numbers for the persons hand. They can see this variable. Also, two numbers for the dealer's invisable hand (except when they win and show it).

This seems simple in words, but for realistic sake, is it possible to make it so it pulls from a 'deck' of 52. So when one 4 is pulled, there is only 3 more to pull. It's not required at all, but for the sake of argument.

Next hump is aces. Aces can be a 1 or an 11. I am guessing that when the random number generates a 1 (Ace) I can output somthing along the lines of "You drew an Ace. Should it be a 1 or an 11". Then just add to the variable. Simple. But is there an easier way? And could it be possible to change it at a later time? (Like if the person has 4 and an ace. Declaring it an 11, he gets a 15. If he draws and gets a 7 or higher he busts. But he should be able to make it a 1)

That is the basic idea. If you love me so very much, and my Russian heratige (or not) my other post explains the optional parts i'm trying to add. Thanks anyways

-G. Matlin, Rabidpunk
• 12-20-2001
novacain
I used to be a blackjack dealer.

My job was to count to only 21 and then take the cash.

I would create a card structure.

int iSuit; //int number for the program to use
char szSuit[64];//string to output to screen
int iFace; //cards int value to be used by prog (0-12 for Ace to King)
int iValue;//cards value 1 to 11 (aces are both)
char szFace[64];//cards string to output

Have one instance for the ordered deck (new one in sequence Ace of Hearts to King of Hearts, Ace of Spades to .........)
A second for the shuffled deck, in random order, to deal from.

Shuffle it by copying cards to from ordered deck to random, empty locations in shuffled deck.

Once you have a shuffled deck you can start to deal.
Check there are enough elements (cards) left to compleate game.
Taking the cards in order from the shuffled deck array and copying them to one of two more arrays, one for the players hand, one for the dealers hand.
An index keeps track of the element of the array you are in.

Work out the totals, -> add splits / doubles / ect later
check for winner, -> blackjacks ect
ask for user input and respond, ->draw, or sit
check for winner.
Output result and update money.

This is fairly easy as the AI for the dealer is simple. I would make it that the daler draws till a predefined 'soft' total say 17. (A hard total does NOT contain an Ace, a soft total does)

Start simple and add more as it works.

(Least that is the way I would do it)
• 12-21-2001
Rabidpunk
Deck
How would I create the deck and how might I randomly pick the card? I belive that's the only problem I have with your response (thanks for it)
• 12-21-2001
Yoshi
I programmed one b4 and it has FACES, ACE 1,11 <=user option to choose, smart AI.
• 12-21-2001
FCF
AI
Hi, i have something to say for the AI of the program. The idea is: first, let the user to have three choices > easy, normal, and hard.
Then, for the easy mode, the program will not "think" anything, just check the card received, if less than 16, hit. Or if bigger, stay.
For the normal mode, the program is smarter, after receiving the cards, it will considered some factors. Eg. percentage to win if hit or stay, persentage to get what card if hit, etc. After that, the program will make conclusion. It will be harder to win. The decision also is random, means that in the same condition, sometimes the program will hit but sometimes it stays.
Finally, the Hard mode. Besides considering the factors above, the program will check the players' cards, to check the condition of the player. If the player get 20 (sure the player will not hit anymore), the program will try to hit although the program receives 17,18, or 19. Also, the program will consider the amount the player bet. If just small amount, and the persentage to win is small, the program will let the user to win to let the player bet bigger next time. The program will think in the "long period", means that big probably you will win little, but lose many!
All the ideas above are just "talk", i am thinking to crete a 21 game, but i think if i want to make the AI like above, i have to put so many time into it. Bye.
• 12-23-2001
C_Coder
Quote:

Finally, the Hard mode. Besides considering the factors above, the program will check the players' cards
Thats cheating, remind me not to play any of your games LOL
• 12-25-2001
FCF
I agree that it sounds cheating...
But, for a human being, if the person is talent, he can memorize all the cards being distributed... (it's true).
So, although the program will be very smart or even undefeatable, it is the challenge ! We still have the chance to win.:)
• 12-29-2001
Dissata
don't know about the rest but for the aces you could do something like

if( playerhand[ace]==TRUE && playertotal >=22) {
ace==1;

}else{
ace==11;
}

or something like that, haven't programmed in a while though:rolleyes:

good luck!
• 12-29-2001
Dissata
also make it simple don't let the user have the opion, just write the function that if you are going to bust cause you have a 23 and an ace with the value of 11 the that ace is now worth 1 and you have a 13

also i would make an array with array for the deck

example:

deck[hearts][4]
deck[clubs][12]

were the first one is a 4 of hearts and the second one is a king of clubs.

this will make it easier when you want to add graphics and make the code easier to read and follow
;)
• 01-05-2002
novacain
>>But, for a human being, if the person is talent, he can memorize all the cards being distributed... (it's true).

Not in my professional experience. Card counters keep a difference of tens to low cards (2-6) and use a formula to determine the amount to bet. This is based on the 'true count'. Better ones use more complicated differences. I have delt to many counters (including a couple of real pro's), I was a very fast dealer (and could count) so I was sometimes sent to confirm a counter.

Something like [((tens-lows) / decks remaining) * table minimum bet]

Casinos work on odds and this pushes the odds into the counters favor. So shuffling machines are now standard in our casino (not possible to count with them).
• 01-06-2002
tim545666
I stayed up pretty late last night making a blackjack game. I just started C++ so if the code is ugly, spaghetti-ish and inefficient it is because I'm so used to writing in BASIC. Anyway, heres the file, no intro because I'm lazy, but the aces do work correctly, dealer stands on 16. My goal for the next month is to make it graphic instead of text, add sound and mouse, and to keep track of scores. Heres the code (written in Bloodshed Dev C++ 4):
#include <stdio.h>
#include <iostream.h>
#include <windows.h>
#include <conio.h>
#include <conio.c>
#include <apvector.h>
#include <stdlib.h>
#include <apstring.h>
#include <apstring.cpp>
#include <time.h>

struct cardtype
{ //TYPE OF DATA USED IN ARRAYS
//USAGE: card[1].suit

int num; //number (1-13)
int suit; //Suit (3-6)
apstring face; //1...9, q, a, (10 = t)
int val; //card's value (although ace is tricky)
};

//FUNCTIONS
void erase (apvector<cardtype>&, apvector<cardtype>&, apvector<cardtype>&);
void shuffle (apvector<cardtype>&);
void set (apvector<cardtype>&);
void deal (apvector<cardtype>&, apvector<cardtype>&, apvector<cardtype>&);
bool pturn (apvector<cardtype>&, apvector<cardtype>&,int &, int &);
void bust ();
void win ();
void lose();
void push ();
bool cturn (apvector<cardtype>&, int &, int &);

int main(int argc, char *argv[])
{
START:
clrscr();
srand(time(NULL));

//INITIALIZING CARD ARRAYs
apvector<cardtype> card (53); //THE DECK
apvector<cardtype> phand (53); //PLAYER'S HAND
apvector<cardtype> chand (53); // Computer's hand

//ERASING THE ARRAYs
erase (card, phand, chand);

//SHUFFLING DECK
shuffle (card);

//MESSING WITH FACES AND ACTAL VALUES OF THE DECK
set(card);

//DEALING HANDS (10 cards each)
deal(card, phand, chand);

//PLAYER HITS
int pcds = 2; //num of player's cards he has taken
int total = 0; //total of player's cards

while (pturn (phand, chand, pcds, total) && total <=21)
{}
if (total >21)
bust();
else
{
int ccds = 2; //num of computers cards
int ctotal = 0; //total of comp's cards
while (cturn (chand, ccds, ctotal) && ctotal <16){}
cout << endl << endl << "DEALER GETS A " << ctotal;
if (ctotal >21) win ();
if (ctotal == total) push();
if (ctotal > total && ctotal <=21) lose();
if (ctotal < total) win();
}

//ENDING PROGRAM
TRYAGAIN:
char again=' ';
cout << endl <<endl <<"Press y if you would like to play again or q to quit: ";
cin >> again;;
if (again == 'y' || again == 'Y')
goto START;
else if (again != 'q' && again !='Q')
goto TRYAGAIN;

Sleep(1000);
return 0;
}

void erase (apvector<cardtype> &card, apvector<cardtype> &phand, apvector<cardtype> &chand)
{
for (int i = 1; i<=52; i++) {
card[i].num=0;
card[i].suit=0;
card[i].val=0;
card[i].face=' ';
phand[i]=card[i]; //card i is a blank card, doing this is quicker
chand[i]=card[i];}
}

void shuffle (apvector<cardtype> &card)
{
for (int i = 1; i<=52; i++)
{
RERANDOM:
card[i].num=rand()%13+1; //random card
card[i].suit=rand()%4+3; //random suit
bool uni=true; //uni=unique
if (i!=1) //if its 1, it is unique
{
for(int t=1; t<i; t++) //check loop
{
if (card[i].suit==card[t].suit && card[i].num==card[t].num) //if cards are the same
bool uni=false;
}
}
if (uni==false) //if card isnt unique
goto RERANDOM; //rerandomize the card
}
}

void set (apvector<cardtype> &card)
{
for (int i = 1; i <=52; i++){
if (card[i].num >=2 && card[i].num<=9)
{
card[i].val=card[i].num;
}
if (card[i].num==10)
{
card[i].val=card[i].num;
card[i].face="10";
}
else if (card[i].num==11)
{
card[i].val=10;
card[i].face="J";
}
else if (card[i].num==12)
{
card[i].val=10;
card[i].face="Q";
}
else if (card[i].num==13)
{
card[i].val=10;
card[i].face="K";
}
else if (card[i].num==1)
{
card[i].val=11;
card[i].face="A";
}
if (card[i].num==2)
card[i].face="2";
else if (card[i].num==3)
card[i].face="3";
else if (card[i].num==4)
card[i].face="4";
else if (card[i].num==5)
card[i].face="5";
else if (card[i].num==6)
card[i].face="6";
else if (card[i].num==7)
card[i].face="7";
else if (card[i].num==8)
card[i].face="8";
else if (card[i].num==9)
card[i].face="9";

}
}

void deal (apvector<cardtype> &card, apvector<cardtype> &phand, apvector<cardtype> &chand)
{
//GIVING PLAYER HIS CARDS
for (int i = 1; i<=10; i++)
phand[i]=card[i];

//GIVING COMPUTER HIS CARDS
for (int i = 1; i<=10; i++)
chand[i]=card[i+10];
}

bool pturn (apvector<cardtype> &phand, apvector<cardtype> &chand,int &pcds, int &total)
{
clrscr();
cout << "Dealer is showing a "<<chand[1].face<<char(chand[1].suit)<<endl;
cout << endl << endl << endl << endl;
cout << "You have a " << phand[1].face << char(phand[1].suit);
if (pcds <=2)
{cout << " and a " << phand[2].face << char(phand[2].suit);}
else
cout << ", a " << phand[2].face << char(phand[2].suit);
if (pcds ==3)
{cout << ", and a " << phand[3].face << char(phand[3].suit);}
else if (pcds >=4)
cout << ", a " << phand[3].face << char(phand[3].suit);
if (pcds ==4)
{cout << ", and a " << phand[4].face << char(phand[4].suit);}
else if (pcds >=5)
cout << ", a " << phand[4].face << char(phand[4].suit);
if (pcds ==5)
{cout << ", and a " << phand[5].face << char(phand[5].suit);}
else if (pcds >=6)
cout << ", a " << phand[5].face << char(phand[5].suit);
if (pcds ==6)
{cout << ", and a " << phand[6].face << char(phand[6].suit);}
else if (pcds >=7)
cout << ", a " << phand[6].face << char(phand[6].suit);
if (pcds ==7)
{cout << ", and a " << phand[7].face << char(phand[7].suit);}
else if (pcds >=8)
cout << ", a " << phand[7].face << char(phand[7].suit);
if (pcds ==8)
{cout << ", and a " << phand[8].face << char(phand[8].suit);}
else if (pcds >=9)
cout << ", a " << phand[8].face << char(phand[8].suit);
if (pcds ==9)
{cout << ", and a " << phand[9].face << char(phand[9].suit);}
cout << endl <<"Which brings your total to ";

//DOES THE FOLLOWING 3 TIMES BECAUSE IF YOU THINK ABOUT IT
total = 0; //IT MAY NEED TO HAPPEN 3 TIMES

TRYAGAIN: //line it goes to after an invalid response
for (int t = 1 ;t <=3; t++)
{
total = 0;
for (int i = 1; i <=pcds; i++) //adding up total
total=total+phand[i].val;
if (total >21)
{
for (int i = 1; i<=pcds; i++) //if u bust it checks for aces counted as 11's
{
if (phand[i].val==11) //if it finds 1 it changes the ace's value to a 1
{phand[i].val=1; break;}
} //(clever isnt it?)
}
}

cout << total;

if (total >21)
{return false;}

char hits; //hit or stay variable

cout << endl <<endl <<"Would you like to hit or stand? ";
cin >> hits;
if (hits == 'h' || hits == 'H')
{pcds++; return true;}
else if (hits=='s' || hits=='S')
return false;
else{cout << "INVALID RESPONSE"; goto TRYAGAIN;}

}

void bust ()
{
cout <<endl << endl << "YOU BUSTED!!!!";
}

void lose ()
{
cout <<endl << endl << "YOU LOST!!!!";
}

void win ()
{
cout <<endl << endl << "YOU WON!!!!";
}

void push ()
{
cout <<endl << endl << "PUSH (YOU TIED)";
}

bool cturn (apvector<cardtype> &chand, int &ccds, int &ctotal)
{
//DOES THE FOLLOWING 3 TIMES BECAUSE IF YOU THINK ABOUT IT
//IT MAY NEED TO HAPPEN 3 TIMES

for (int t = 1 ;t <=3; t++)
{
ctotal = 0;
for (int i = 1; i <=ccds; i++) //adding up total
ctotal=ctotal+chand[i].val;
if (ctotal >21)
{
for (int i = 1; i<=ccds; i++) //if u bust it checks for aces counted as 11's
{
if (chand[i].val==11) //if it finds 1 it changes the ace's value to a 1
{chand[i].val=1; break;}
} //(clever isnt it?)
}
}

if (ctotal > 15) return false; // stand on 16
if (ctotal <=15) {ccds++;return true;} //hit on 15 and above

}

Please respond and tell me how I can make this more efficient, becuase I keep finding ways to make the code shorter and faster, and I know there's a lot more in there.
• 01-07-2002
Unregistered
Then you're playing 21 at home with a friend, being dumb =P

Real BlackJack, the dealer hits until 17 or higher. They don't play out the odds. Aswell, in real blackjack, one card of the dealer is seen.

For a deck of cards man, just make an array.

iDeck[52];

Then just randomly assign the deck the numbers from 1 to 52.

0-12 = Hearts (0 = 2, 12 = Ace)
13-26 = Diamonds (13 = 2, 26 = Ace)
27-39 = Spades (27 = 2, 39 = Ace)
40-52 = Clubs (40 = 2, 52 = Ace)

There, now you have a deck, a suit value and the card value. It should be easy to go from here

(I'm tired, those numbers may be wrong)
• 01-11-2002
FCF
:) A good code ! Keep it up!:p