The Playing Card Structure (Poker II)

Drawing cards from a deck is an activity requiring more effort than flagging an element in an array, which was demonstrated in last week’s Lesson. Such code works, but it’s best to set details about the card when it’s drawn, noting its face value and suit, for example. Such complex information is best placed into a structure.

Here’s the playing_card structure I devised:

struct playing_card {
    wchar_t suit;
    char face[3];
    int value;
};

The suit member is of the wchar_t type, a wide character. This member holds the symbol for Spades (♠), Clubs (♣), Hearts (♥), and Diamonds (♦). It not only helps the code recognize the suit, it stores the unicode character value for output.

The face member is a string that holds the card’s face value. This includes the string representation of values 2 through 10, but also the characters “A” for Ace, “J” for Jack, “Q” for Queen, and “K” for King.

The value member holds the card’s numeric value, 1 through 13.

The updated draw() function from last week’s code now selects a random card from the deck and then fills and returns a playing_card structure. The structure’s members are based on the random card drawn, assigning the suit, face value string, and integer value to the card. Here’s the overhauled code:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <locale.h>
#include <wchar.h>

#define CARDS 52

struct playing_card {
    wchar_t suit;
    char face[3];
    int value;
};

struct playing_card draw(int d[]);

int main()
{
    int deck[CARDS];
    struct playing_card hand;
    int x;

    /* seed the randomizer */
    srand((unsigned)time(NULL));
    /* activate wide characters */
    setlocale(LC_ALL,"en_US.UTF-8");

    /* initialize the deck */
        /* 0 = card not drawn
           1 = card drawn */
    for( x=0; x<CARDS; x++)
        deck[x] = 0;

    /* draw a card */
    hand = draw(deck);
    wprintf(L"You drew the %s of %lcs\n",
            hand.face,
            hand.suit
          );

    return(0);
}

struct playing_card draw(int d[])
{
    wchar_t suits[] = { 0x2660, 0x2663, 0x2665, 0x2666 };
    struct playing_card c;
    int r;

    /* search for an available card */
    while(1)
    {
        r = rand() % CARDS;
        if( d[r] == 0 )
            break;
    }

    /* mark the card as drawn */
    d[r] = 1;

    /* assign suit */
    c.suit = suits[r/13];

    /* assign card value */
    c.value = r % 13 + 1;
    
    /* assign face wide string */
    switch(c.value)
    {
        case 1:
            sprintf(c.face,"A");
            break;
        case 11:
            sprintf(c.face,"J");
            break;
        case 12:
            sprintf(c.face,"Q");
            break;
        case 13:
            sprintf(c.face,"K");
            break;
        default:
            sprintf(c.face,"%d",c.value);
    }
    
    return(c);
}

This code mixes both standard character and wide character output, required to generate the card suit symbols.

Here are a few sample runs:

You drew the K of ♦s
You drew the J of ♠s
You drew the 9 of ♣s

You may not see the wide characters in some terminal windows. I recommend changing the font or trying a different terminal window program if the special characters don’t appear.

The next step to creating a card game is to modify the code to draw and store a given number of cards. After that, the cards must be evaluated, depending on what type of game you want to play. This process continues in next week’s Lesson.

Leave a Reply