Hi guys, My name is Leonard E Norwood Jr. I'm a senior at Norfolk State University and a beginning of programming. I'm just working on a small program on my own time to practice. So you're familiar with the playing cards and the logic of dealing a deck with 4 players. I've been working on it for some time, but I think I'm making beginner's mistakes with this program. Take a look:

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

#define  TRUE 1
#define  FALSE 0
#define  BOOL int
#define NUM_SUITS 4
#define NUM_RANKS 13

int main(void)
{
BOOL in_hand[NUM_SUITS],[NUM_RANKS] = {FALSE};
int num_cards, rank, suit;
int num_cards = 13;

const char rank_code[] = {'2','3','4','5','6','7','8',
                          '9','t','j','q','k','a'};
const char suit_code[] = {'c','d','h','s'};

srand( time(NULL));

printf("Your hand :");
while(num_cards > 0) {
suit = rand() % NUM_SUITS;
rank = rand() % NUM_RANKS;
if (!in_hand[suit][rank]) {
    in_hand[suit][rank] = true;
    num_cards--;
    printf(" %c%c", rank_code[rank], suit_code[suit]);
   }
  }
printf("\n");
return 0;
}

So this is what I got so far. The plan was to make sure I have 52 possible cards out of this array, and make sure to declare them right so once I compile and ran this, up to 4 players display 13 cards of each deck. And Multiple runs makes sure to produce a different deck without duplicates. rand() and srand() are to ensure that each out put is random and not produce to same outputs. However due to how I made this, I got this many error and warnings:

-bash-4.3$ gcc deckOfCardsLNorwood.c
deckOfCardsLNorwood.c: In function `main':
deckOfCardsLNorwood.c:17: error: syntax error before '[' token
deckOfCardsLNorwood.c: At top level:
deckOfCardsLNorwood.c:23: error: syntax error before '(' token
deckOfCardsLNorwood.c:26: error: syntax error before string constant
deckOfCardsLNorwood.c:26: error: conflicting types for 'printf'
deckOfCardsLNorwood.c:26: note: a parameter list with an ellipsis can't match an empt y parameter name list declaration
deckOfCardsLNorwood.c:26: error: conflicting types for 'printf'
deckOfCardsLNorwood.c:26: note: a parameter list with an ellipsis can't match an empty parameter name list declaration
deckOfCardsLNorwood.c:26: warning: data definition has no type or storage class
deckOfCardsLNorwood.c:29: error: initializer element is not constant
deckOfCardsLNorwood.c:29: warning: data definition has no type or storage class
deckOfCardsLNorwood.c:30: error: syntax error before "if"
deckOfCardsLNorwood.c:33: error: syntax error before string constant
deckOfCardsLNorwood.c:33: warning: data definition has no type or storage class
deckOfCardsLNorwood.c:36: error: syntax error before string constant
deckOfCardsLNorwood.c:36: warning: data definition has no type or storage class
-bash-4.3$ cat deckOfCardsLNorwood.c

Oh I almost forgot to add that I'm using PuTTy to practice. PuTTy must have some C89 format or something because when I tried to do this thing words for word off the book and ran it, due to C99 stuff I put in there, it had some errors on it. It seems despite my attempts, I still failed to declare boolean variable designed to make a comparison to make sure the card selected in the "deck" is the same as the card picked to avoid duplicates, arrays NUM_SUITS, NUM_RANK, code_suit, and code_rank. I thought I did, but if the compiler said I didn't then, I didnt. I just need some kind of help fix these errors and get this code running again. If the problem turns out to be the boolean declarations and other things that should have been settled in the beginning, I need to be pointed the right way. I await the help

It appears to me one of your problems is here:

BOOL in_hand[NUM_SUITS],[NUM_RANKS] = {FALSE};

When you're declaring a multidimensional array there isn't supposed to be a comma separating the dimensions. Due to the nature of compiling c source code, this error right near the start could be creating the other errors:

BOOL in_hand[NUM_SUITS][NUM_RANKS] = {FALSE};

On a side note, one way, in c, to create a unique random selection is to use an array of all the possibilities, choose one at random and assign it to your new collection then overwrite it by moving each one below it up one. By changing the max for rand to reflect how much of the array is being used, each random choice will only be of the ones that are left. The beauty of this is that even if rand chooses the same number twice the selection will still be unique.

Edited 1 Year Ago by tinstaafl

An other way to approach your problem is to 'huffle the deck' before dealing it out ...

Take a look:

/* 52Cards.c */

/*
    You can find file "readline.h" at:
    http://developers-heaven.net/forum/index.php/topic,2580.msg2864.html#msg2864

    You can find file "Cvec.h" at:
    http://developers-heaven.net/forum/index.php/topic,2580.0.html

*/

#include "readLine.h" /* re. myAssert */
#include <time.h>


const char kinds[] = {'S', 'C', 'H', 'D'};
const char values[] = {'2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A'};


typedef struct
{
    char kind;
    char val;

} Rec;

void freeVrec( Rec* p )
{
    /* NO dynamic memory was used here, so NONE to free  ... */
}


/* NEED BOTH definitions above: typedef Rec  and  freeVrec ...
   and then can include ... */

#include "Cvec.h"

#define Card Rec /* equate */


void getNewDeck( Cvec* cards )
{
    int i, j;
    for( i = 0; i < 4; ++ i )
    {
        for( j = 0; j < 13; ++ j )
        {
            Card c;
            c.kind = kinds[i];
            c.val = values[j];
            push_backCvec( cards, &c  );
        }
    }
}
void shuffleDeck( Cvec* cards )
{
    int i, j, count = cards->size;
    Card tmp;
    while( count-- )
    {
        i = rand() % cards->size;
        j = rand() % cards->size;

        /* swap */
        tmp = cards->ary[i];
        cards->ary[i] = cards->ary[j];
        cards->ary[j] = tmp;
    }
}
void showCards( const Cvec* cards )
{
    int i;
    for( i = 0; i < cards->size;  )
    {
        printf( "%c%c  ", cards->ary[i].val, cards->ary[i].kind ) ;
        if( ++i % 13 == 0 ) putchar('\n');
    }
}


int main()
{
    Cvec cards, hand[4];
    int i;
    initCvec( &cards ); /* must initial to work ok ... */
    for( i  = 0; i < 4; ++ i )
    {
        initCvec( &hand[i] );
        reserveCvec( &hand[i], 13 );
    }

    srand( time(0) );

    getNewDeck( &cards );
    puts( "Showing new deck of cards ..." );
    showCards( &cards );

    printf( "\ncapacity = %d, size = %d\n", cards.cap, cards.size );

    shuffleDeck( &cards );
    puts( "\nShowing shuffled deck ..." );
    showCards( &cards );
    putchar('\n');

    /* fill up each of 4 hands */
    for( i = 0 ; i < 52 ;  )
    {
        int j;
        for( j = 0; j < 4; ++ j )
        {
            push_backCvec( &hand[j], &cards.ary[i] );
            ++i;
        }
    }

    for( i = 0; i < 4; ++ i )
    {
        printf( "\nShowing hand[%d]:\n", i );
        showCards( &hand[i] );
        clearCvec( &hand[i] );
    }


    clearCvec( &cards ); /* clear all dynamic memory whe done */

    puts( "\nAfter clearCvec..." );
    printf( "capacity = %d, size = %d\n", cards.cap, cards.size );

    printf( "\nPress 'Enter' to continue/exit ... " );
    fflush( stdout );
    return 0;

}

Edited 1 Year Ago by David W

Comments
Definitely the best approach

Ok then, I see what you two are getting at. I knew I needed to somehow use Boolean variables carefully with arrays. I got the logic behind the playing cards, but translating them into code has been a challenging in many possible ways. So the line 13 shown, may be causing the errors, but at the same time, even without the comma, it's not that easy still...Ok then, so tinstaafl is telling me to create an array for random selection, that way it's a good way to compare the decks. David on the other hand, is telling me to huffle my decks and the way shown.

It should be also possible to still make this happen without a for loop, as help as that one is. But I'm going to try it out. I'll send down the work I did soon.

/* Deals a random hand of cards */

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

#define  TRUE 1
#define  FALSE 0
#define  BOOL int

#define NUM_SUITS 4
#define NUM_RANKS 13

int main()
{

        BOOL in_hand[NUM_SUITS][NUM_RANKS] = {FALSE};
        int num_cards = 13, rank, suit;

        const char rank_code[] = {'2','3','4','5','6','7','8',
                                  '9','t','j','q','k','a'};
        const char suit_code[] = {'c','d','h','s'};
        srand( time(NULL));


        printf("Your hand :");
        while(num_cards > 0) {
        suit = rand() % NUM_SUITS;
        rank = rand() % NUM_RANKS;
        if (!in_hand[suit][rank]) {
           in_hand[suit][rank] = TRUE;
           num_cards--;
           printf(" %c%c", rank_code[rank], suit_code[suit]);
          }
        }
        return 0;
}

This is my program now, it works without any errors. Now I just have to modify it so there are 4 players instead of one.

Before going any further I urge you to look at David W's post again ... creating a full deck, shuffling it, and taking cards from it.
His approach is going to work for dealing one hand, n hands, discard piles, hidden and face-up hands... Any card game, and scales trivially for two-deck games. It will also evolve brilliantly into an object oriented version in C++ or whatever.

Your code is fine for one hand, but it will will get more and more difficult and error-prone as you add stuff. You will have to check each random card against every hand, every card that has been changed or discarded. Not to mention games with 2 or more decks of cards.

Plus there's something nasty about using randoms like that... when there's just one card left you will have to test somewhere between 1 and MAX_INTEGER (modal value 52) random cards just to find it. Hardly a clean efficient design!

Edited 1 Year Ago by JamesCherrill

Here's a simple example of a more Object Oriented approach in C, that shows how to deal and handle multiple decks in one shoe. I also tightened up my earlier shuffling algorithm by moving indexes rather than values:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define CARDS_IN_HAND 5
#define NUM_SUITS 4
#define NUM_RANKS 13
#define SHOE_SIZE 1
#define DECK_SIZE  (NUM_RANKS * NUM_SUITS * SHOE_SIZE)
#define PLAYERS_PER_TABLE 6
const char RANKS[] = "23456789TJQKA";
const char SUITS[] = "SDHC";
typedef struct newCard
{
    char rank;
    char suit;
}Card;
typedef struct newPlayer
{
    char name[30];
    Card hand[CARDS_IN_HAND];
}Player;
void MakeNewDeck(Card newDeck[NUM_RANKS * NUM_SUITS * SHOE_SIZE])
{
    int deckNum = 0;
    for (; deckNum < SHOE_SIZE; deckNum++)
    {
        int suit = 0;
        for (; suit < NUM_SUITS; suit++)
        {
            int rank = 0;
            for (; rank < NUM_RANKS; rank++)
            {
                Card temp;
                temp.rank = RANKS[rank];
                temp.suit = SUITS[suit];
                newDeck[(suit* NUM_RANKS) + rank] = temp;
            }
        }
    }

}
void ShuffleDeck(Card shuffledDeck[NUM_RANKS * NUM_SUITS * SHOE_SIZE])
{
    Card newDeck[NUM_RANKS * NUM_SUITS * SHOE_SIZE];
    MakeNewDeck(newDeck);
    int limit = DECK_SIZE - 1;
    int cardIndex = 0;
    for (; cardIndex < DECK_SIZE; cardIndex++)
    {
        int nextIndex = 0;
        if (limit != 0)
        {
            nextIndex = rand() % limit;
        }
        shuffledDeck[cardIndex] = newDeck[nextIndex];
        newDeck[nextIndex] = newDeck[limit--];
    }
    return;
}

void DealCards(Card deck[NUM_RANKS * NUM_SUITS * SHOE_SIZE], Player players[], int numPlayers)
{
    if (numPlayers * CARDS_IN_HAND > DECK_SIZE)
    {
        printf("%s", "Too many players");
        return;
    }
    int cardNum = 0;
    for (; cardNum < CARDS_IN_HAND; cardNum++)
    {
        int playerNum = 0;
        for (; playerNum < numPlayers; playerNum++)
        {
            players[playerNum].hand[cardNum] = deck[(cardNum * numPlayers) + playerNum];
        }
    }
}
int main()
{
    srand(time(NULL));
    Card deck[NUM_RANKS * NUM_SUITS * SHOE_SIZE];
    ShuffleDeck(deck);
    Player table[PLAYERS_PER_TABLE];
    DealCards(deck, table, PLAYERS_PER_TABLE);
    int player = 0;
    for (; player < 6; player++)
    {
        printf("%i - ", player);
        int card = 0;
        for (; card < CARDS_IN_HAND - 1; card++)
        {
            printf("%c%c,", table[player].hand[card].rank, table[player].hand[card].suit);
        }
        printf("%c%c\n", table[player].hand[card].rank, table[player].hand[card].suit);
    }
    return 0;
}

Edited 1 Year Ago by tinstaafl

This article has been dead for over six months. Start a new discussion instead.