Playing cards/C

From Rosetta Code
< Playing cards(Redirected from Playing Cards/C)
Playing cards/C is part of Playing Cards. You may find other members of Playing Cards at Category:Playing Cards.

(The code lacks some checking, and I have not deeply tested it yet)

#include <stdio.h>
 
/* fits into a .h */
#include <stdlib.h>
#include <string.h>
 
#define N_SUITS 4
#define N_PIPS 13
#define N_CARDS (N_SUITS*N_PIPS)
 
enum cardsuit {
CLUBS, HEARTS, SPADES, DIAMONDS
};
enum cardpip {
TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT,
NINE, TEN, JACK, QUEEN, KING, ACE
};
enum decktype {
EMPTY_DECK, FULL_DECK
};
 
struct deckcard {
enum cardsuit suit;
enum cardpip pip;
};
typedef struct deckcard card_t;
 
struct deck {
card_t *refcards[N_CARDS];
card_t *cards[N_CARDS];
int icards[N_CARDS];
int n;
};
typedef struct deck deck_t;
/* end of .h */
 
 
const char *suits[N_SUITS] = {
"clubs", "hearts", "spades", "diamonds"
};
const char *pips[N_PIPS] = {
"2", "3", "4", "5", "6", "7", "8", "9", "10",
"jack", "queen", "king", "ace"
};
 
static int rrand(int m)
{
return (int)((double)m * ( rand() / (RAND_MAX+1.0) ));
}
 
card_t *new_card(enum cardpip p, enum cardsuit s)
{
card_t *c;
 
c = malloc(sizeof(card_t));
c->suit = s; c->pip = p;
return c;
}
 
void destroy_card(card_t *c)
{
free(c);
}
 
void print_card(card_t *c)
{
printf("(%s,%s)", pips[c->pip], suits[c->suit]);
}
 
static void generate_fullset(card_t **cset)
{
int suit, pip;
 
for(suit=0; suit < N_SUITS; suit++) {
for(pip=0; pip < N_PIPS; pip++) {
cset[suit*N_PIPS + pip] = new_card(pip, suit);
}
}
}
 
deck_t *new_deck(enum decktype t)
{
deck_t *d;
int i;
 
d = malloc(sizeof(deck_t));
if ( d != NULL ) {
generate_fullset(d->refcards);
switch(t) {
case EMPTY_DECK:
for(i=0; i < N_CARDS; i++) d->cards[i] = NULL;
d->n = 0;
break;
case FULL_DECK:
for(i=0; i < N_CARDS; i++) {
d->cards[i] = d->refcards[i];
d->refcards[i] = NULL;
d->icards[i] = i;
}
d->n = N_CARDS;
break;
default:
fprintf(stderr, "hm?\n");
}
}
return d;
}
 
void destroy_deck(deck_t *d)
{
int i;
for(i=0; i < N_CARDS; i++) {
free(d->refcards[i]);
free(d->cards[i]);
}
free(d);
}
 
void shuffle_deck(deck_t *d)
{
int i, t, r;
 
for(i=0; i < d->n; i++) {
r = rrand(d->n);
t = d->icards[i];
d->icards[i] = d->icards[r];
d->icards[r] = t;
}
}
 
card_t *deck_deal(deck_t *d)
{
int c;
card_t *uc;
 
if ( d->n == 0 ) return NULL;
d->n--;
c = d->icards[d->n];
d->refcards[c] = d->cards[c];
d->cards[c] = NULL;
/* make a copy for the user */
uc = new_card(d->refcards[c]->pip, d->refcards[c]->suit);
return uc;
}
 
void deck_addcard(deck_t *d, card_t *c)
{
int r;
int p, s;
 
if ( d->n == N_CARDS ) {
free(c);
return;
}
if ( c == NULL ) {
/* add a random card */
do {
r=rrand(N_CARDS);
} while ( d->refcards[r] == NULL );
d->cards[r] = d->refcards[r];
d->refcards[r] = NULL;
d->icards[d->n++] = r;
} else {
p = c->pip;
s = c->suit;
if ( d->cards[s*N_PIPS + p] == NULL ) {
d->cards[s*N_PIPS + p] = d->refcards[s*N_PIPS + p];
d->refcards[s*N_PIPS + p] = NULL;
d->icards[d->n++] = s*N_PIPS + p;
}
free(c);
}
}
 
void print_deck(deck_t *d)
{
int i;
 
for(i=0; i < d->n; i++) {
print_card(d->cards[d->icards[i]]);
printf("\n");
}
}
 
/* testing */
int main()
{
deck_t *a_deck;
card_t *a_card;
 
a_deck = new_deck(FULL_DECK);
shuffle_deck(a_deck);
a_card = deck_deal(a_deck);
printf("picked a ");
print_card(a_card);
printf("\n\n");
free(a_card);
print_deck(a_deck);
destroy_deck(a_deck);
return 0;
}