A
Army1987
I have written a function to shuffle a deck of cards, as follows:
#include <time.h>
#include <stdlib.h>
#define MAX_DECKSIZE 52
typedef struct card {
enum rank { Joker, Ace, Jack = 11, Queen, King } rank;
enum suit { Spades, Clubs, Diamonds, Hearts } suit;
} card_t;
typedef struct deck {
int size;
card_t card[MAX_DECKSIZE];
} deck_t;
void shuffle(deck_t * deckptr)
{
static unsigned int times = 0;
int i;
srand((unsigned)clock() ^ (unsigned)time(0) + times++);
for (i = 0; i < deckptr->size; i++) {
int r = rand() / (RAND_MAX / (deckptr->size - i) + 1);
if (r) {
card_t tmp = deckptr->card;
deckptr->card = deckptr->card[i + r];
deckptr->card[i + r] = tmp;
}
}
}
The problem is: this cannot portably shuffle a deck, because it
requires rand() to have at least 52! states. (If it has less
states, the pigeonhole principle shows that not all permutations
are possible.) Should I call the function several times, hoping
that the increment of clock() (and possibly of time(0)) will be
unpredictable enough? Is there anything less ridiculous I could
do? Should I resort to system-specific ways <ot>e.g. reading from
/dev/urandom<ot>? I don't need it to be cryptographically secure
(I didn't even bother to cope with the bias due to RAND_MAX + 1
not always being a multiple of deckptr->size - i), but I wouldn't
like that some permutations are more likely than others by several
orders of magnitude.
#include <time.h>
#include <stdlib.h>
#define MAX_DECKSIZE 52
typedef struct card {
enum rank { Joker, Ace, Jack = 11, Queen, King } rank;
enum suit { Spades, Clubs, Diamonds, Hearts } suit;
} card_t;
typedef struct deck {
int size;
card_t card[MAX_DECKSIZE];
} deck_t;
void shuffle(deck_t * deckptr)
{
static unsigned int times = 0;
int i;
srand((unsigned)clock() ^ (unsigned)time(0) + times++);
for (i = 0; i < deckptr->size; i++) {
int r = rand() / (RAND_MAX / (deckptr->size - i) + 1);
if (r) {
card_t tmp = deckptr->card;
deckptr->card = deckptr->card[i + r];
deckptr->card[i + r] = tmp;
}
}
}
The problem is: this cannot portably shuffle a deck, because it
requires rand() to have at least 52! states. (If it has less
states, the pigeonhole principle shows that not all permutations
are possible.) Should I call the function several times, hoping
that the increment of clock() (and possibly of time(0)) will be
unpredictable enough? Is there anything less ridiculous I could
do? Should I resort to system-specific ways <ot>e.g. reading from
/dev/urandom<ot>? I don't need it to be cryptographically secure
(I didn't even bother to cope with the bias due to RAND_MAX + 1
not always being a multiple of deckptr->size - i), but I wouldn't
like that some permutations are more likely than others by several
orders of magnitude.