Thread: Help with my blackjack code thanks :D

  1. #1
    Registered User
    Join Date
    Nov 2005
    Posts
    2

    Help with my blackjack code thanks :D

    Is it possbile to take out the class stuff and the program would still work? and i been told i could slim it down to make the code shorter, any suggestions would help ^_^
    Code:
    #include <windows.h>
    #include <iostream> 
    using namespace std; 
     
    char cardNames[13][52] = {
     "two", "three", "four", "five", "six", //names of cards
     "seven", "eight", "nine", "ten", "jack",
     "ace", "king", "queen"
    };
     
    char cardSuits[4][52] = {
     "clubs", "spades", "hearts", "diamonds" //the 4 suits
    };
     
    char cardValues[13] = {
     2,3,4,5,6,7,8,9,10,10,10,11,12 //the values of the cards
    };
     
    void CardToString(int card)
    {
     cout<<cardNames[card%13]<<" of "<<cardSuits[card/13]<<endl<<flush; //ex:seven of diamonds
    }
     
    class cPlayer
    {
    public:
     int playerCards[52]; //the cards the player has
     int bet,money;       //declares bet and money
     int hasDoubled;     //declares double
     
     cPlayer()
     {
      money = 100; //player start with 100 dollars 
      ClearHand();
     }
     
     void ClearHand()
     {
      for(int j=0;j<52;j++)
       playerCards[j]=0;
     
      bet = 0;
      hasDoubled = -1; // < 0 indicates not doubling
     }
     
     void ShowHand()
     {
      int j,k;
      for(j=0;j<52;j++)
       for(k=0;k<playerCards[j];k++)
        CardToString(j);
     }
     
     void TakeCard(int c)
     {
      playerCards[c%52]++;
     }
     
     void PlaceBet(int n)
     {
      bet = n;
     }
     
     bool Has10()
     {
      int j,k;
     
      for(k=0;k<4;k++)
       for(j=8;j<12;j++)
        if(playerCards[k*13+j]>0)
         return true;
      return false;
     }
     
     bool HasAce()
     {
      int k;
     
      for(k=0;k<4;k++)
       if(playerCards[k*13+12]>0)
        return true;
      return false;
     }
     
     int HandValue()
     {
      int j;
      int value = 0;
      int numAces = 0;
      for(j=0;j<52;j++)
      {
       if((j+1)%13!=0)  //aces have special handling
        value+=playerCards[j]*cardValues[j%13];
       else
        numAces+=playerCards[j];
      }
     
      if(hasDoubled > 0) //if the player has doubled, and had at least one ace
      {
       value += (hasDoubled); //all aces for double have value of 1 
       numAces -= hasDoubled; //remove them from the count
      }
      
      if(numAces >= 1) //if we have at least one ace
       if(value + 11 + numAces - 1 <=21) //and can make it 11 without busting
       {
        value+=11;  //use the ace as an 11
        numAces--;
       }
      value+=numAces;   //use the remaining aces as 1 each
     
      return value;
     }
     
    
     //we'll set the default behavior for hitting to the dealer rules
     virtual bool Hit()
     {
      if(HandValue()<17) //dealer stays on 17 and over, otherwise hits
       return true;
      return false;
     }
     
     //dealer never doubles
     virtual bool Double()
     {
      return false;
     }
    };
     
    class cDealer: public cPlayer
    {
    public:
     cDealer() 
     {
      cPlayer();
     }
    };
     
    class cHuman: public cPlayer
    {
    public:
     cHuman() 
     {
      cPlayer();
     }
     
     bool Double()
     {
      char input = ' ';
      cout<<"Would you like to double? y or n"<<endl;
      cin>>input;
     
      if(input=='n' || input == 'N')
       return false;
     
      int k;
      hasDoubled = 0;  //flag that we've doubled 
      for(k=0;k<4;k++)
       hasDoubled += playerCards[k*13+12]; //add up the number of aces the player has
      return true;
     }
     
     bool Hit()
     {
      int curHand = HandValue();
      if(curHand<12)
      {
       if(curHand>=9)
       {
        if(Double())
        {
         cout<<"Player has DOUBLED!"<<endl;
         bet *= 2;  //double our bet
         return true;
        }
       }
       else
        return true;
      }
     
      char input = ' ';
      cout<<"Would you like to hit? y or n"<<endl;
      cin>>input;
     
      if(input=='n' || input == 'N')
       return false;
     
      return true;
     }
    };
     
    int main()
    {
     bool valid = false; //vaild
     
     int numDecks = 3; //this keeps track of the number of decks we're playing with
     int deckOfCards[52]; //this is the deck we will be drawing cards 
     
     int numPlayers = 2;
     cPlayer ** players = new cPlayer*[numPlayers]; //our players (player 0 is always the dealer)
     
     int bet; //temp bet variable
     int card; //temp card variable
     
     int j=0,k=0; 
     
     players[0] = new cDealer();
     for(j=1;j<numPlayers;j++)
      players[j] = new cHuman();
     
    
     
     /*****************
     This is where the game will loop 
     when playing multiple hands
     *****************/
     bool done = false;
     while (!done)
     {
      srand(GetTickCount()); //randomize the timer based on the tickcount
     
      //fill up our deck with all the cards
      for(j=0;j<52;j++)
       deckOfCards[j]=numDecks;
     
      //the players
      players[0]->ClearHand();
      players[1]->ClearHand();
     
      //take bets
      for(j=1;j<numPlayers;j++)
      {
       bet = -1;
       while(bet<0)
       {
        cout<<"How much would you like to bet,  player "<<j<<"?"<<endl;
        cin>>bet;
       }
       players[j]->bet = bet;
       cout<<"Player "<<j<<" has bet $"<<bet<<endl;
      }
     
      //initial deal
      //deal each player, including the dealer, two cards
      for(k=0;k<2;k++)
       for(j=0;j<numPlayers;j++)
       {
        valid = false;
        while(!valid)
        {
         card = rand()%52;
         if(deckOfCards[card]>0)
         {
          deckOfCards[card]--;
          valid=true;
         }
        }
        if(j+k==0)
        {
         cout<<"Dealer is showing a ";
         CardToString(card);
         cout<<endl;
        }
        players[j]->TakeCard(card);
       }
     
      //actual game play
      for(j=1;j<numPlayers;j++)
      {
       //check to see if player has blackjack
       if(players[j]->HandValue()==21)
       {
        cout<<"BLACKJACK for Player "<<j<<"!"<<endl;
        if(players[0]->Has10() || players[0]->HasAce())
        {
         if(!players[0]->HasAce())
         {//dealer has a 10
          players[j]->money+=players[j]->bet;
          cout<<"Dealer has a 10 but no ace, player wins $"<<players[j]->bet<<endl;
         }
         else
         {
          cout<<"Dealer has an ace, player must wait."<<endl;
         }
        }
        
       }
       else  
       {
        cout<<"Player "<<j<<" has the following hand:"<<endl;
        players[j]->ShowHand();
        cout<<"Player "<<j<<" has "<<players[j]->HandValue()<<endl;
     
        //continue dealing cards until the player says stop or doubles
        while(players[j]->hasDoubled < 0 && players[j]->Hit())
        {
         valid=false;
         while(!valid)
         {
          card = rand()%52;
          if(deckOfCards[card]>0)
          {
           deckOfCards[card]--;
           players[j]->TakeCard(card);
           valid=true;
          }
         }
         cout<<endl;
         cout<<"Player "<<j<<" has the following hand:"<<endl;
         players[j]->ShowHand();
         cout<<"Player "<<j<<" has "<<players[j]->HandValue()<<endl;
         cout<<endl;
        }
       }
      }
     
      //dealer's turn
      if(players[0]->HandValue()==21)
      {
       // if the dealer has blackjack then dealer wins
       
       for(j=1;j<numPlayers;j++)
        if(players[j]->hasDoubled > -1)  //if a player has doubled
         players[j]->bet /= 2;   //restore original bet amount
       cout<<"Dealer has BLACKJACK!"<<endl;
      }
      else
       while(players[0]->Hit())
       {
        valid=false;
        while(!valid)
        {
         card = rand()%52;
         if(deckOfCards[card]>0)
         {
          deckOfCards[card]--;
          players[0]->TakeCard(card);
          valid=true;
         }
        }
       }
     
      //final tally to see who wins and loses
      j=0;
      
      int playerValue, dealerValue = players[j]->HandValue();
     
      cout<<"Dealer has the following hand:"<<endl<<flush;
      players[j]->ShowHand();
      cout<<"Dealer has "<<dealerValue<<endl;
      cout<<endl;
      
      
      for(j=1;j<numPlayers;j++)
      {
       playerValue = players[j]->HandValue();
     
       cout<<"Player "<<j<<" has "<<playerValue<<endl;
       
       players[j]->ShowHand();
       cout<<endl;
     
       if(playerValue<=21) //see if player busts
       {
        //if the dealer busts or the player
        //scored higher (ties go to dealer)
        if(dealerValue > 21 || playerValue > dealerValue) 
        {
         players[j]->money+=players[j]->bet;
         cout<<"You win"<<endl;
        }
        else
        {
         players[j]->money-=players[j]->bet;
         cout<<"You lose"<<endl;
        }
       }
       else
       {
        players[j]->money-=players[j]->bet;
        cout<<"You lose"<<endl;
       }
       cout<<"Player "<<j<<" has $"<<players[j]->money<<endl;
      }
      char input = ' ';
      cout<<"Would you like to play another hand? y or n"<<endl;
      cin>>input;
     
      if(input=='n' || input == 'N')
       done = true;
     }
     
     //end of the game
     for(j=0;j<numPlayers;j++)
      delete players[j];
     delete [] players;
     
    }

  2. #2
    Registered User
    Join Date
    Nov 2005
    Posts
    545
    I just tries to compile that and supposedly there is a problem with you declaration of the function rand()

  3. #3
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    Ahhh I'm a bit tired to really look through this whole thing and suggest how to slim it down. :/

    One thing I did notice while glancing at it was this.

    Code:
    void CardToString(int card)
    {
     cout<<cardNames[card%13]<<" of "<<cardSuits[card/13]<<endl<<flush; //ex:seven of diamonds
    }
    There is no need to call a function to do a one line output. It's just extra overhead for the program. Not to say it's that big of a deal with the memory and disk space we have, today, but it's still a bad habit.

    Secondly, it does look a little long for a blackjack game, but then I don't know what it's really capable of. As for classes, I saw your class and I personally think you can throw the whole thing out of the window if you wanted. When you're writing a program with only one class, you can probably do without that one class. It's not like it will be confused or interfere with anything else.
    Sent from my iPad®

  4. #4
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> There is no need to call a function to do a one line output... it's still a bad habit.

    This is wrong in most cases. You should use separate functions for each task (within reason). That avoids duplicating code which is harder to debug and maintain. In this case, that method is called from several different places, so if you wanted to change that functionality you would just update the method instead of changing each place it is used and potentially missing one. Of course, the name of the method could use a change, it doesn't exactly do what the name indicates it does.

  5. #5
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    I'd love to agree with you Daved, but the fact is, that function is only called twice in his program.

    Yes, if you're gonna repeat a line of code over and over and over again, it's a good idea to put it into a function. In this case, you aren't using it that much and it's really just a waste.
    Sent from my iPad®

  6. #6
    Registered User
    Join Date
    Nov 2005
    Posts
    2
    so i dont need to declare class Cplayer and just need to put the functions?

  7. #7
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    You don't need to have the class, but it is a bad idea to remove it. Why switch from good design to bad design?

    Same goes for the function, SlyMaelstrom. Why use bad design when good design techniques are available? Why advise somebody to use poor programming techniques when the code already uses good ones?

  8. #8
    Cat Lover
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    109
    Well, just testing it out. It compiles fine with VS.net at least.

    Now, why did you include windows.h? I don't see anything looking through there that needs it.

    2. The game doesn't work. :P
    It appears to count all face cards as 11, so you can get a blackjack with queen and 10 for example. I notice you declared cardnames, presumably in order of value, with "ten", "jack",
    "ace", "king", "queen".

    3. endl flushes as well, you don't need cout << endl << flush.

    4. If you're going to complain about useless code, complain about this
    Code:
     void PlaceBet(int n)
     {
      bet = n;
     }
    , which is not even called at all.

    5. In HandValue,
    Code:
     int HandValue()
     {
      int j;
      int value = 0;
      int numAces = 0;
      for(j=0;j<52;j++)
      {
       if((j+1)%13!=0)  //aces have special handling
        value+=playerCards[j]*cardValues[j%13];
       else
        numAces+=playerCards[j];
      }
    The line numAces += playerCards[j], shouldn't that be numAces++? If they have an ace numaces is increased by one right? Possibly playerCards[j] == 1 when it's an ace, but then it's still pointless extra work, and makes no sense.

    //dealer never doubles
    virtual bool Double()
    {
    return false;
    }
    Pointless?

    Anyway, I've got to head off now, but there's a bunch of things to start off with.

  9. #9
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    Code:
    char cardNames[13][52] = {
     "two", "three", "four", "five", "six", //names of cards
     "seven", "eight", "nine", "ten", "jack",
     "ace", "king", "queen"
    };
     
    char cardSuits[4][52] = {
     "clubs", "spades", "hearts", "diamonds" //the 4 suits
    };
     
    char cardValues[13] = {
     2,3,4,5,6,7,8,9,10,10,10,11,12 //the values of the cards
    };
    Don't declare global variables.

    I would add more classes rather than get rid of classes. How about a Deck class which contains Card objects, and which can be shuffled(). Card objects could have two members: 1-13 for the value and 1-4 for the suit.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Enforcing Machine Code Restrictions?
    By SMurf in forum Tech Board
    Replies: 21
    Last Post: 03-30-2009, 07:34 AM
  2. Values changing without reason?
    By subtled in forum C Programming
    Replies: 2
    Last Post: 04-19-2007, 10:20 AM
  3. Obfuscated Code Contest
    By Stack Overflow in forum Contests Board
    Replies: 51
    Last Post: 01-21-2005, 04:17 PM
  4. Interface Question
    By smog890 in forum C Programming
    Replies: 11
    Last Post: 06-03-2002, 05:06 PM
  5. Replies: 0
    Last Post: 02-21-2002, 06:05 PM