Playing cards/C

From Rosetta Code
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) <lang c>#include <stdio.h>

/* fits into a .h */

  1. include <stdlib.h>
  2. include <string.h>
  1. define N_SUITS 4
  2. define N_PIPS 13
  3. 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;

}</lang>