Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

In class we discussed how we could use classes to implement Black Jack. In this

ID: 3554255 • Letter: I

Question

In class we discussed how we could use classes to implement Black Jack. In this lab you will do exactly that.

Your game should play a single hand of black jack (which may involve several turns). You should print the cards that the dealer is holding and the cards that the player is holding.

You should create a full deck of cards and store them in a list to represent the deck. Then use random's shuffle to shuffle the deck. Remove cards from the deck to put them in the player or dealer's hand.

You will also need to devise a way for the user to input your moves. In this version of the game you only need to implement "hit" (take another card from the dealer) or "stand" (take no more cards):

Your game should correctly detect if either the player or the dealer busts to determine the winner.

Explanation / Answer

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>


/*--------------
* This part of the code deals with a deck of cards
*/

struct Card {
enum Suit { Spades, Clubs, Hearts, Diamonds } suit;
int value;
char * const name;
} Deck [52] =
{
{Spades, 2, "2"},
{Spades, 3, "3"},
{Spades, 4, "4"},
{Spades, 5, "5"},
{Spades, 6, "6"},
{Spades, 7, "7"},
{Spades, 8, "8"},
{Spades, 9, "9"},
{Spades, 10, "10"},
{Spades, 10, "Jack"},
{Spades, 10, "Queen"},
{Spades, 10, "King"},
{Spades, 11, "Ace"},

{Clubs, 2, "2"},
{Clubs, 3, "3"},
{Clubs, 4, "4"},
{Clubs, 5, "5"},
{Clubs, 6, "6"},
{Clubs, 7, "7"},
{Clubs, 8, "8"},
{Clubs, 9, "9"},
{Clubs, 10, "10"},
{Clubs, 10, "Jack"},
{Clubs, 10, "Queen"},
{Clubs, 10, "King"},
{Clubs, 11, "Ace"},

{Hearts, 2, "2"},
{Hearts, 3, "3"},
{Hearts, 4, "4"},
{Hearts, 5, "5"},
{Hearts, 6, "6"},
{Hearts, 7, "7"},
{Hearts, 8, "8"},
{Hearts, 9, "9"},
{Hearts, 10, "10"},
{Hearts, 10, "Jack"},
{Hearts, 10, "Queen"},
{Hearts, 10, "King"},
{Hearts, 11, "Ace"},


{Diamonds, 2, "2"},
{Diamonds, 3, "3"},
{Diamonds, 4, "4"},
{Diamonds, 5, "5"},
{Diamonds, 6, "6"},
{Diamonds, 7, "7"},
{Diamonds, 8, "8"},
{Diamonds, 9, "9"},
{Diamonds, 10, "10"},
{Diamonds, 10, "Jack"},
{Diamonds, 10, "Queen"},
{Diamonds, 10, "King"},
{Diamonds, 11, "Ace"},
};

            /* 0 means the corresponding card hasn't been
               drawn; otherwise, the card has been drawn
            */
static char Cards_drawn [52];

            /* The number of cards that haven't been drawn yet */
static int Cards_left;



    /* Methods of the Cards "package"
    */
static void Cards_init(void)
{
Cards_left = sizeof(Deck)/sizeof(Deck[0]);
memset(Cards_drawn,0,sizeof(Cards_drawn));
}


static void Cards_print(const int index)
{
const struct Card * cp;
assert( index >= 0 && index < sizeof(Deck)/sizeof(Deck[0]) );
cp = Deck + index;
printf("Card %s of ",cp->name);
switch(cp->suit)
{
    case Spades:
     printf("spades");
     break;
    
    case Clubs:
     printf("clubs");
     break;
    
    case Hearts:
     printf("hearts");
     break;
    
    case Diamonds:
     printf("diamonds");
     break;
    
    default:
     assert(0 /*can't happen*/);
   }
}

            /* Draw a card and return its index    */
static int Cards_draw(void)
{
int offset;
register int i;
if( Cards_left < 1 )
    printf(" No cards left to draw! "), exit(4);

offset = Cards_left == 1 ? 1 : 1 + (rand() % Cards_left);

        /* In the following loop, we search for a
            offset-th card in the deck that hasn't been drawn.
            In other words, we search for offseth-th zero element
            of an array Cards_drawn
        */
for(i=0; i<sizeof(Deck)/sizeof(Deck[0]); i++)
    if( Cards_drawn[i] )
      continue;
    else if( --offset == 0 )
    {
      Cards_drawn[i] = 1;
      Cards_left--;
      return i;
    }
assert( 0 /* Can't happen */);
}


        /* Given a card's index, return ints value    */
static int Cards_value(const int index)
{
assert( index >= 0 && index < sizeof(Deck)/sizeof(Deck[0]) );
return Deck[index].value;   
}


static int is_ace(const int value)
{ return value == 11; }


/*--------------
*    A neuron that learns how to play. One neuron per player
*/

#define PERFECT_SCORE 21

struct Player
{
int threshold;    /* A learning parameter */

const char * name;    /* Player's name */
int no_wins;        /* The total number of wins    */

        /* The following are the current status of the hand */
int score;        /* score so far, with aces counted as 11    */
int no_aces;        /* The number of aces so far            */
} Player1 =
{5, "player 1", 0, 0, 0},
Player2 =
{15, "player 2", 0, 0, 0};

            /* Have a given player take a card        */
static void take_card(struct Player * player)
{
const int index = Cards_draw();
const int value = Cards_value(index);
player->score += value;
if( is_ace(value) )
    player->no_aces++;
printf(" %s has drawn ",player->name); Cards_print(index);
}

            /* Give the best interpretation of the current    */
            /* hand. An ace can have the value 1 or 11    */
            /* We interpret as many aces as 11s as we can    */
            /* keeping the score under PERFECT_SCORE    */
static int best_score(const struct Player * player)
{
int score = player->score;
int aces = player->no_aces;
assert( score > 0 && aces >= 0 && aces <= 4 );
while( aces>0 && score > PERFECT_SCORE )
    score -= 10, aces--;
return score;
}


static void note_victory(struct Player * player)
{
printf(" %s has won ",player->name);
player->no_wins++;
}
            /* Init the hand        */
static void hand_init(struct Player * player)
{
player->score = 0;
player->no_aces = 0;
}


            /* This is the goal function, which decides if */
            /* to continue to draw cards        */
static int q_continue(const struct Player * player)
{
int score = player->score;
int aces = player->no_aces;
assert( score > 0 && aces >= 0 && aces <= 4 );
return score - 2*aces < player->threshold;
}

            /* The following two functions implement the
               most trivial learning algorithm, which adjusts
               the threshold based on a loss
               Note that it is actually the most trivial
               implementation of a back-propagation
            */
static void learn_from_overdraft(struct Player * player)
{
printf(" %s has overdrew",player->name);
player->threshold--;
printf(" threshold is now %d ",player->threshold);
}

static void learn_from_underdraft(struct Player * player)
{
printf(" %s should've continued ",player->name);
player->threshold++;
printf(" threshold is now %d ",player->threshold);
}

           
/*----------
* Main module
*/

             /* Plays one game    */
static void play_game(void)
{
hand_init(&Player1);
hand_init(&Player2);
Cards_init();

                /* Each of the players draws initially */
                /* two cards            */
take_card(&Player1);
take_card(&Player1);
take_card(&Player2);
take_card(&Player2);
for(;;)
{
    const int score1 = best_score(&Player1);
    const int score2 = best_score(&Player2);
    const int wants_continue1 = q_continue(&Player1);
    const int wants_continue2 = q_continue(&Player2);

    printf(" %s score is %d, %s score is %d",
          Player1.name, score1, Player2.name, score2);
    if( score1 > PERFECT_SCORE && score2 > PERFECT_SCORE )
    {                /* both players overdrew    */
      learn_from_overdraft(&Player1);
      learn_from_overdraft(&Player2);
      return;                /* game is over        */
    }
    if( score1 > PERFECT_SCORE )
    {
      learn_from_overdraft(&Player1);
      note_victory(&Player2);
      return;
    }
    if( score2 > PERFECT_SCORE )
    {
      learn_from_overdraft(&Player2);
      note_victory(&Player1);
      return;
    }
    if( score1 == PERFECT_SCORE )
    {
      note_victory(&Player1);
      return;
    }
    if( score2 == PERFECT_SCORE )
    {
      note_victory(&Player2);
      return;
    }
    if( !wants_continue1 && !wants_continue2 )
    {            /* nobody wants to continue    */
      if( score1 > score2 )
      {
          learn_from_underdraft(&Player2);
          note_victory(&Player1);
      }
      else
      {
          learn_from_underdraft(&Player1);
          note_victory(&Player2);
      }
      return;
    }
    if( wants_continue1 )
      take_card(&Player1);
    if( wants_continue2 )
      take_card(&Player2);
}
}
        /* This is just a demo that draws some n cards    */
static void draw_some(void)
{
const int n=10;
register int i;

srand(time(0));        /* Seed the random number generator
                   with the current timestamp */
Cards_init();

printf(" Draw %d cards at random ",n);
for(i=0; i<n; i++)
{
    int index = Cards_draw();
    printf("Draw #%d: ",i+1);
    Cards_print(index);
    printf(" of value %d ",Cards_value(index));
}
printf(" Done ");
}


void main(void)
{
const int n=20;
register int i;

srand(time(0));        /* Seed the random number generator
                   with the current timestamp */


for(i=0; i<n; i++)
    play_game();
   
printf(" ==>Total %d game played. %s won %d, %s won %d ",
       n,Player1.name,Player1.no_wins,Player2.name,Player2.no_wins);
}

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote