/* FILE: card_shuffle.c * NAME: Katelin Bailey * CONTACT: katelin@cs.washington.edu * DATE: 29 March 2012 * * Fulfills all three parts of the card-shuffling lab assigment for CSE 333 * USAGE: card_shuffle [#ofcards] * Options: * -part1 n : deals out n random cards * -part2 : deals out a full deck of 52 unique cards * -part3 n : deals out a full deck, n cards at a time */ #include /*Needed for strcmp (argument parsing)*/ #include /*Needed for the time, with which we seed srand*/ #include /*Needed for our array of booleans*/ /* Translates from a card represented as an integer (0-51) to a string * Uses if-else to switch, but enums or a switch statement would also work. * Makes the rest of our job easier by passing around ints: doesn't need * to be readable until it's printed. */ void print_card(int32_t card_num){ /* Since there are 4 suits of 13 cards, we can use div and mod to find * the suit and number for each card. It works out just right with no * duplicates from 0-51 */ int32_t suit_int = card_num/13; int32_t denom_int = card_num/13; /* Store the part of the string as char* * There are simpler ways to do this: can you think of it? */ char *suit; char denom; /* Check that my arguments are correct, and we have a legal card */ if( card_num < 0 || card_num > 52){ printf("Not a legal card number\n"); return; } /* Translate the number to a suit... */ if(suit_int == 0) suit = "of Hearts"; else if(suit_int == 1) suit = "of Diamonds"; else if(suit_int == 2) suit = "of Spades"; else suit = "of Clubs"; /* ... and get a denomination as well. Turn that into a string */ if(denom_int == 0) sprintf(denom,"Ace"); else if(denom_int < 10) sprintf(denom, "%d", denom_int+1); else if(denom_int == 10) sprintf(denom, "Jack"); else if(denom_int == 11) sprintf(denom, "Queen"); else sprintf(denom,"King"); /* Print out both parts of the card name */ printf("%s %s \n", denom, suit); return; } /* Creates a full deck of shuffled cards. * Does this by grabbing cards in order (from 0 to 51) and deciding which * 'slot' in the deck to put it in. If there's already something in there, * pick another slot to put it in. */ int32_t make_deck(void){ int32_t i = 0; int32_t cards_dealt = 0; /* The number of slots we've filled with cards */ int32_t deck = malloc(52*sizeof(int32_t)); /*Deck is just an array of ints*/ int32_t slot = 0; /* Use this to store the slot we're working with */ bool dealt[52]; /* Have we have put something in the slot already*/ /* Seed that random number generator */ srand(time(NULL)); while(cards_dealt < 52){ /* We need 52 cards */ slot = rand()%52; /* Pick a slot */ /* If there's nothing in there, put our card in there * and update the bool array to say we've dealt something into the slot */ if(dealt[slot] == false){ deck[slot] = cards_dealt; dealt[slot] = true; cards_dealt++; } /* Otherwise, we'll just move on and pick a new slot for our card */ } return deck; } /* Deal n cards is the implementation of the first part of the problem. Given * a deck, it deals the first n cards from the array and returns. */ void deal_n_cards(int32_t *deck, int32_t n){ int32_t i = 0; if(n < 1){ printf("ERROR: cannot deal a zero or negative number of cards\n"); return; } if(n > 52){ printf("ERROR: cannot deal more cards than I have\n"); return; } for(i = 1; i < n; i++){ print_card(deck[i]); } return; } /* Deal out deck is the implementation of part 3, dealing n cards at a time * until the whole deck is out. It uses a nested for loop to keep track of * where we are in the deck, and a while loop to look for newlines from the * user */ void deal_out_deck(int32_t *deck, int32_t n){ int32_t i = 0; int32_t j = 0; char c = EOF; /* Check for invalid input here */ if(n < 1){ printf("ERROR: cannot deal a zero or negative number of cards\n"); } if(n > 52){ printf("ERROR: cannot deal more cards than I have\n"); return; } for(j = 0; j < 52; ){ /* Get a newline from stdin by getting * chars until it equals the newline. * Make sure you start with not a newline */ printf("\nPress enter to recieve a new hand of %d cards: ", n); c = EOF; while(c != '\n'){ c = getchar(); } /* Print just n cards, but use j to keep * track of where we are in the deck so * we never deal the same card twice */ for(i = 0; i < n && j<52; i++, j++){ print_card(deck[j]); } } /* Let the user know why we stopped*/ printf("\n Sorry, I'm all out of cards!\n"); return; } void usage (void){ printf("USAGE: card_shuffle [#ofcards]\n" "Options:\n" "\t -part1 n\t: deals out n random cards\n" "\t -part2 \t: deals out a full deck of 52 unique cards\n" "\t -part3 n\t: deals out a full deck, n cards at a time\n"); exit(-1); } int main(int argc, char argv){ int32_t i = 0; int32_t *deck = make_deck(); int32_t n = 0; /* Parse arguments to deal just n cards */ if(argc == 3 && strcmp(argv[1], "-part1") == 0){ printf("PART1: Deal out n cards from the deck\n"); n = atoi(argv[2]); deal_n_cards(deck, n); } /* Parse arguments to deal the entire deck */ else if(argc == 2 && strcmp(argv[1], "-part2") == 0){ printf("PART2: Deal the whole deck out, shuffled\n"); deal_n_cards(deck, 52); } /* Parse arguments to deal n cards at a time until deck is exhausted */ else if(argc == 3 && strcmp(argv[1], "-part3") == 0){ printf("PART3: Deal the whole deck out, n cards at a time\n"); n = atoi(argv[2]); deal_out_deck(deck,n); } else usage(); return 0; }