Thread: blackjack- keep card from being drawn again

  1. #1
    Registered User
    Join Date
    Sep 2006
    Posts
    27

    blackjack- keep card from being drawn again

    Hello all,

    I am working on writing a blackjack program. I have the main program working, but I want to program to run off of only one deck so the same card cannot be drawn twice in one hand.

    The code for the program is:

    Code:
    #include <iostream>
    #include <ctime> //used in random card generator
    #include <string>
    using namespace std;
    
    
    void rules(void);
    void betcheck(int&, int&);
    void deckgen(int[4][13]);
    void deal(int[4][13], int[4][13], int [52], int, int&, int&, int&, string&, string&, string&, string&);
    void dealer (int[4][13], int[4][13], int [52], int, int&, int, string, string, string, string);
    void randcard(int[4][13], int[4][13], int [52], int, int&, int&, string&, string&);
    void cardcheck(int[4][13], int[52], int);
    void settle(int, int, int&, int&);
    
    int main(void)
    {
    	cout << "It's time to play blackjack!\n" << endl << endl;
    
    	int bet = 0;  
    	int chips = 1000;
    	char play = 'Y';
    
    	rules();  // Player is shown rules for betting
    
    	do
    	{
    		betcheck(chips, bet); // Player places bet and it is checked against the rules
    
    		srand( (unsigned)time( NULL ) ); //onverts seconds to an unsigned int for random card generator
    		
    		int deck[4][13];
    		int card[4][13];
    		int cardsp[52];
    		int ddealertot = 0, ddace = 0, pplayertot = 0, carddrawn = 0;
    		string suittext, cardtext, suittex, cardtex, suitt, cardt;
    
    		deckgen(deck);//creates deck and names card values
    		deal(deck, card, cardsp, carddrawn, ddealertot, pplayertot, ddace, suittex, cardtex, suitt, cardt);
    		dealer(deck, card, cardsp, carddrawn, ddealertot, ddace, suittex, cardtex, suitt, cardt);
    		settle (pplayertot, ddealertot, chips, bet);
    
    
    		cout << "Play again?(y/n)  ";//Player decides if he wants to play again
    		cin >> play;
    		cout << endl;
    	}while (play == 'y' || play == 'Y');
    } 
    
    void rules(void)
    {
    	cout << "The rules:\n";
    	cout << "     Bet must be in multiples of five dollars.\n";
    	cout << "     Minimum bet of $5.\n";
    	cout << "     Maximum bet of $100.\n";
    	cout << "     Bet cannot decrease during the same hand.\n";
    	cout << endl;
    	cout << endl; 
    
    	cout << "Your initial chip total is $1000.\n"  << endl << endl << endl;
    	
    }
    
    void betcheck(int& total_chips, int& final_bet)
    {
    	int bet;
    
    	cout << "Bet:              ";//Player inputs first bet
    	cin >> bet;
      
        while (bet < 5)// Player bets less than minimum bet
        { 
    		cout << "Your bet must be between 5 and 100.\n";
            cout << endl << "Bet:              ";
            cin >> bet;
        }
    
    	while (bet > 100)//Player bets more than maximum bet
    	{
    		cout << "Your bet must be between 5 and 100.\n";
    		cout << endl << "Bet:              ";
    		cin >> bet;
    	}
    
    	while (bet % 5 != 0)// Player did not bet in a mulitple of 5
        { 
    		cout << "You can only bet in multiples of 5." << endl;
            cout << endl << "Bet:              ";
            cin >> bet;
        }
    
        while (bet > total_chips)//Player bet more than he had
        {
              cout << "You cannot bet more than your chip count." << endl;
              cout << endl << "Bet:              ";
    		  cin >> bet;
        }
    
        while (bet < final_bet)//Player bet less than previous bet
        {
              cout << "You cannot bet lower than your previous bet." << endl;
              cout << endl << "Bet:              ";
              cin >> bet;
    	}
    
    	final_bet = bet;
        total_chips -= final_bet;
    	cout << endl << "Chips:    " << total_chips << endl << endl;
    }
    
    void deckgen(int deckdeck[4][13])
    {
    	int num;
    
    	for (int i = 0; i <= 3; i++)
    		{
    			for (int j = 0; j <= 12; j++)
    			{
    				if (j < 9)
    					num = j+2;
    				else if (j <12)
    					num = 10;
    				else num = 11;
    				deckdeck[i][j] = num;
    
    			}
    		}
    
    	
    
    }
    
    void randcard(int deckdeck[4][13], int cardcard[4][13], int cardsplayed[52], int cardd, int& suitrand, int& cardrand, string& suitname, string& cardname)
    {
    	int slow = 0, shigh = 4;
    	int clow = 0, chigh = 13;
    	char cardgood = 'n';
    	char dupcard = 'n';
    	int ncard = 1;
    
    	for (int k = 0; k <= 3; k++)
    	{
    		for (int l = 0; l <= 12; l++)
    		{cardcard[k][l]= ncard;
    		ncard++;
    		}}
    
    
    	do
    	{
    	suitrand = slow + (double)rand()/(double) RAND_MAX*(shigh - slow);
    	cardrand = clow + (double)rand()/(double) RAND_MAX*(chigh - clow);
    
    	cout << "suit: " << suitrand << "  card: " << cardrand << "  cardcard: " << cardcard[suitrand][cardrand]<< endl;
    
    	for (int i = 0; i < 52; i++)
    	{
    		if (cardsplayed[i] == cardcard[suitrand][cardrand])
    			dupcard = 'y';
    		if (dupcard == 'y') cout << "DUPLICATE CARD" << endl;
    	}
    		if (dupcard == 'n')
    		{cardsplayed[(cardd)] = cardcard[suitrand][cardrand];
    
    		//cout << "in cardcheck, cardd = " << cardd << endl;
    		//cout << "in cardcheck, cardsplayed " << cardsplayed[cardd] << endl;
    
    		cardd = cardd +1;
    
    		cardgood = 'y';
    
    		//cout << "in cardcheck, cardgood = " << cardgood << endl;
    		}
    	}while (cardgood == 'n');
    
    	//Naming suits.
    	
    	switch(suitrand){
    		case 0: 
    			suitname = "clubs";
    			break;
    		case 1: 
    			suitname = "diamonds";
    			break;
    		case 2: 
    			suitname = "hearts";
    			break;
    		case 3: 
    			suitname = "spades";
    			break;}
    	
    	//Naming Cards.
    
    	switch(cardrand){
    		case 0: 
    			cardname = "two";
    			break;
    		case 1: 
    			cardname = "three";
    			break;
    		case 2: 
    			cardname = "four";
    			break;
    		case 3: 
    			cardname = "five";
    			break;
    		case 4: 
    			cardname = "six";
    			break;
    		case 5: 
    			cardname = "seven";
    			break;
    		case 6: 
    			cardname = "eight";
    			break;
    		case 7: 
    			cardname = "nine";
    			break;
    		case 8: 
    			cardname = "ten";
    			break;
    		case 9: 
    			cardname = "jack";
    			break;
    		case 10: 
    			cardname = "queen";
    			break;
    		case 11: 
    			cardname = "king";
    			break;
    		case 12: 
    			cardname = "ace";
    			break;}
    }
    
    void deal(int deckdeck[4][13], int cardcard[4][13], int playedcards[52], int cardd, int& dealertot, int& playertot, int& dace, string& suitte, string& cardte, string& suittexttext, string& cardtexttext)
    {
    	int place = 0; // Player first has zero aces
    	char hit; //Player decides if he wants to hit his hand
    	int suitnum;//value from 0-3 of suits, ordered clubs, diamonds, hearts, spades
    	int cardnum;//value from 0-12 of cards, ordered 2-10 then jack, queen, king, ace
    	int suitnumber, cardnumber;
    	string suittext, cardtext;
    	int deck[4][13];
    	int card[4][13];
    	int cardspl[52];
    
    	// array storing cards that have been played is re-set
    	for (int i = 1; i < 52; i++)
    	{
    		cardspl[i] = 60;
    	}
    
    	//Player's 1st two cards are randomly generated
    
    	randcard(deck, card, cardspl, cardd, suitnum, cardnum, suittext, cardtext);
    	if (cardnum == 12)
    		place = place + 1;
    	playertot = playertot + deckdeck[suitnum][cardnum];
    	cout << "Your cards:       ";
    	cout << cardtext << " of " << suittext << endl;
    	
    	randcard(deck, card, cardspl, cardd, suitnum, cardnum, suittext, cardtext);
    	if (cardnum == 12)
    		place = place + 1;
    	playertot = playertot + deckdeck[suitnum][cardnum];
    	cout << "                  " << cardtext << " of " << suittext << endl << endl;
    	
    	//Dealer's first two cards are generated
    
    	randcard(deck, card, cardspl, cardd, suitnum, cardnum, suitte, cardte);
    	dealertot = dealertot + deckdeck[suitnum][cardnum];
    	cout << "The dealer's cards:   ";
    	cout << cardte << " of " << suitte << endl;
    	cout << "                  and ???" << endl << endl;
    	if (cardnum == 12)
    		dace = dace + 1;
    	
    	randcard(deck, card, cardspl, cardd, suitnumber, cardnumber, suittexttext, cardtexttext);
    	dealertot = dealertot + deckdeck[suitnumber][cardnumber];
    	if (cardnumber == 12)
    		dace = dace + 1;
    	if (playertot == 21)
    		cout << "Blackjack!!!" << endl << endl;
    
    	//Player plays his hand
    
    	while (playertot < 21)
    	{
    		cout << "Hit/stand (h/s):  ";
    		cin >> hit;
    		if (hit == 'h' || hit == 'H')
    		{
    			randcard(deck, card, cardspl, cardd, suitnum, cardnum, suittext, cardtext);
    			playertot = playertot + deckdeck[suitnum][cardnum];
    			cout << "                  " << cardtext << " of " << suittext << endl << endl;
    			if (cardnum == 12)
    				place = place + 1;
    			if (playertot > 21 && place > 0)
    			{
    				playertot = playertot - 10;
    				place = place - 1;
    			}
    		}
    		else
    			break;
    	}
    
    	if (playertot > 21)
    		cout  << "Bust:             " << playertot << endl << endl;
    
    	if (playertot <= 21)
    		cout << endl << "Your total:       " << playertot << endl << endl;
    }
    
    void dealer(int deckdeck[4][13], int cardcard[4][13], int playedcards[52], int carddr, int& dealertot, int dace, string suitfirst, string cardfirst, string suittextt, string cardtextt)
    {
    	int suitnum;
    	int cardnum;
    	string suittext, cardtext;
    	int deck[4][13];
    	int card[4][13];
    	int cardspl[52];
    	int cardd;
    	
    
    	//Dealer's two cards are shown
    
    	cout << "The dealer's hand:    " << cardfirst << " of " << suitfirst << endl;
    	cout << "                  " << cardtextt << " of " << suittextt << endl;
    	
    	if (dealertot == 21)
    		cout << endl << "Dealer blackJack" << endl;
    
    	//Dealer's hand is played, hits on anything less than a 17 as per casino rules
    
    	while (dealertot < 17)
    	{
    		randcard(deck, card, cardspl, cardd,  suitnum, cardnum, suittext, cardtext);
    		cout << "                  " << cardtext << " of " << suittext << endl;
    		dealertot = dealertot + deckdeck[suitnum][cardnum];
    
    		if (cardnum == 12)
    			dace = dace + 1;
    
    		if (dealertot > 21 && dace > 0)
    		{
    			dealertot = dealertot - 10;
    			dace = dace - 1;
    		}
    	}
    	cout << endl << "Dealer's total:   " << dealertot << endl << endl;
    }
    
    void settle(int player_total, int dealer_total, int& total_chips, int& final_bet)
    {
    	if (player_total == dealer_total)
    	{
    		cout << "                  Push" << endl << endl;
            total_chips += final_bet;	   
    	}
    
        if (player_total <= 21 &&  dealer_total > 21)
    	{
    		cout << "                  You Won" << endl << endl;
    		total_chips = total_chips + 2 * final_bet;
    	}
    
        else if (player_total <= 21 && player_total > dealer_total)
    	{
    		cout << "                  You Won" << endl << endl;
    		total_chips = total_chips + 2 * final_bet;
    	}
    	
        else if (player_total <= 21 && player_total < dealer_total)
    		cout << "                  You Lost" << endl << endl;
    
        else if (player_total > 21 && dealer_total <= 21)
    		cout << "                  You Lost" << endl << endl;
    
        else if (player_total > 21 && dealer_total > 21 && player_total != dealer_total)
        {
    		cout << "                  Push" << endl << endl;
            total_chips += final_bet;	   
    	}
    
    	cout << "New Chip Total:   " << total_chips << endl << endl;
    }
    The portion of the code that I am having problems with in in my random card generator randcard().

    Here, I get a random suit suitrand, and a random card, cardrand. Cardcard[suitrand][cardrand] is an integer between 1 and 52 that I have assigned all of the cards in the deck. As I draw them, I want to see if the card has alrady been drawn by checking it against the array cardsplayed[]. The values in cardsplayed[] are initially set at 60, but as I draw cards, if I do not find the value of cardcard[suitrand][cardrand] in the array, I want to add it in the cardd'th spot, where cardd is the number of cards that have been drawn. If I do find the value of cardcard[suitrand][cardrand] in the array, I want to draw another card and check that.

    My problems are that cardd is not increasing each time I draw a card, the cardsplayed[] array is not storing the values like I want it to, and duplicate cards are still allowed.

    I realise that this is a long post, but thank you for your assistance.

    J

  2. #2
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    Well, without changing your current implementation (though if I could, I definitely would), your easiest bet would be a static boolean array in your randcard() function.
    Code:
    static bool dealt[52] = { 0 };
    
    do {
       suitrand = slow + (double)rand()/(double) RAND_MAX*(shigh - slow);
       cardrand = clow + (double)rand()/(double) RAND_MAX*(chigh - clow);
    } while(dealt[13*suitrand+cardrand]);
    
    dealt[13*suitrand+cardrand] = true;
    Or something of that nature. Of course, you'll have to reset this variable everytime you wish to collect the cards. It would likely be easier if this was actually a global variable or passed to any function that may need it.
    Last edited by SlyMaelstrom; 09-11-2006 at 12:18 AM.
    Sent from my iPadŽ

  3. #3
    The larch
    Join Date
    May 2006
    Posts
    3,573
    You could make the deck an array, and use std::random_shuffle() on it. Then you can draw the cards sequentially from the array.

    If you're going to learn classes, you could make things simpler by creating a Card class (value, suit, name).

  4. #4
    Its hard... But im here swgh's Avatar
    Join Date
    Apr 2005
    Location
    England
    Posts
    1,688
    Like anon suggested, add a classes like:

    house class // computer
    deckclass
    generic player class
    player class
    ect..

    It may be that you have to redo most of your program but if it was "OOP" then it would
    be easier to see what is going on and what classes can handel which objects. Of course, the design is all down to you, and if you are not yet into classes, then by all means use
    sly's idea to solve your problem

  5. #5
    Registered User
    Join Date
    Mar 2006
    Posts
    725
    anon's answer is the simplest. Just make an int array or something with 52 values and do a random_shuffle() on it. Whenever you want a new game, just fill the array with 1, 2, ..., 51, 52 in a loop and call random_shuffle() again. You could even put this into its own function eg. resetdeck(int *deck).
    Code:
    #include <stdio.h>
    
    void J(char*a){int f,i=0,c='1';for(;a[i]!='0';++i)if(i==81){
    puts(a);return;}for(;c<='9';++c){for(f=0;f<9;++f)if(a[i-i%27+i%9
    /3*3+f/3*9+f%3]==c||a[i%9+f*9]==c||a[i-i%9+f]==c)goto e;a[i]=c;J(a);a[i]
    ='0';e:;}}int main(int c,char**v){int t=0;if(c>1){for(;v[1][
    t];++t);if(t==81){J(v[1]);return 0;}}puts("sudoku [0-9]{81}");return 1;}

  6. #6
    Registered User
    Join Date
    Sep 2006
    Posts
    27
    Thank you for your input. I will change my program as anon suggested. That is definitely more elegant than what I was attempting to do.

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Yes, implement a deck() class with a couple of methods like
    - shuffle
    - drawCard
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    Quote Originally Posted by JackR
    Thank you for your input. I will change my program as anon suggested. That is definitely more elegant than what I was attempting to do.
    Elegant and aesthetically pleasing, yes, but it's also a complete work over from what you did. You're literally going to keep zero of the code you wrote and you could also write an elegant implementation without OOP. Just giving you an idea of your options. If I were you, I'd stick with what you have. I assume you haven't delved into classes, yet, and the worst way to learn something like that is to sift through some tutorials on syntax trying to modify existing code or ideas. You won't absorb anything and in order to get an elegant Object Oriented approach, you'll likely need to understand classes, the stack data structure, and perhaps dynamic memory. Hope you're up for it.
    Sent from my iPadŽ

  9. #9
    Registered User
    Join Date
    Mar 2006
    Posts
    725
    In response to Sly...

    Code:
    int current_deck[52];
    
    //assume integers 1 to 52 represent cards
    //put the cards in the new deck
    for(int i = 0; i < 52; ++i)
    {
        current_deck[i] = i + 1;
    }
    
    //shuffle the start to the end of the deck
    std::random_shuffle(current_deck+0, current_deck+52);
    
    //the card on top of the deck
    int top = 51;
    
    
    
    //a way to get a card from the top of the deck
    if(top == 0)
    {
        std::cout << "Error: Dealt all cards already!";
    }
    else
    {
        int nextcard = current_deck[top--];
    }
    Code:
    #include <stdio.h>
    
    void J(char*a){int f,i=0,c='1';for(;a[i]!='0';++i)if(i==81){
    puts(a);return;}for(;c<='9';++c){for(f=0;f<9;++f)if(a[i-i%27+i%9
    /3*3+f/3*9+f%3]==c||a[i%9+f*9]==c||a[i-i%9+f]==c)goto e;a[i]=c;J(a);a[i]
    ='0';e:;}}int main(int c,char**v){int t=0;if(c>1){for(;v[1][
    t];++t);if(t==81){J(v[1]);return 0;}}puts("sudoku [0-9]{81}");return 1;}

  10. #10
    Its hard... But im here swgh's Avatar
    Join Date
    Apr 2005
    Location
    England
    Posts
    1,688
    I know its rather old school C++ but if am printing an error message to the screen I send it by cerr and not cout, just another needless input i guess. As cerr sound like error

  11. #11
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    Jafet... I was mostly responding to the idea of scraping what he has for a class construction... nicer in the end... but I don't think it's make a good OOP learning experience.
    Sent from my iPadŽ

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need Help With a BlackJack Program in C
    By Jp2009 in forum C Programming
    Replies: 15
    Last Post: 03-30-2009, 10:06 AM
  2. Bitwise Unwanted Output
    By pobri19 in forum C++ Programming
    Replies: 4
    Last Post: 09-15-2008, 04:07 AM
  3. Vector out of range program crash.
    By Shamino in forum C++ Programming
    Replies: 11
    Last Post: 01-18-2008, 05:37 PM
  4. Segmentation Fault - aaaaaaaah!
    By yogibear in forum C Programming
    Replies: 6
    Last Post: 10-01-2007, 03:21 AM
  5. How can I access a struct (from a header file)?
    By loxslay in forum C++ Programming
    Replies: 3
    Last Post: 10-07-2006, 01:25 PM