John Snow
John Snow

Reputation: 5334

Problems with my random number generator

Im learning basic C on my own and trying to create a poker client. I have an array with cards (called kortArray) and a players hand (called kortHand). My implementation does not shuffle the deck, but add all 52 cards in sequence and then randomly selecting 5 cards from the deck. I've added a flag (called draget) which tells if a card has been picked up befor or not.

Now, when I run the algorithm below, it usually generates five random numbers which makes the player's or computer's hand. But sometimes it generates less then five numbers, even though I've specifically stated to generate five accepted values.

I have two loops, one that runs five times, and the other is nested and runs until it finds a card which hasn't yet been picked. The printf in the middle tells me that this algorithm doesn't always generate five accepted numbers, and when that happens the player's hand contains cards with nonsense-values.

srand((unsigned)(time(0)));
for(i = 0; i < 5; i++) {                        
    int x = rand()%52 + 1;
    while (kortArray[x].draget!=1) {                
        x = rand()%52 + 1;
        if (kortArray[x].draget != 1) {
            printf("%i\n", x);
            kortArray[x].draget = 1;
            kortHand[i] = kortArray[x];
        }
    }
}

Upvotes: 1

Views: 274

Answers (5)

Tobias Langner
Tobias Langner

Reputation: 10808

I'd suggest a different algorithm:

  1. create a random number between 0 and number of cards in deck
  2. assign the card from that position to the appropriate hand
  3. swap the last card to that postion
  4. decrease the number of cards in the deck by 1.
  5. continue with 1 until the necessary number of cards are dealt.

This way, you get rid of the flag and you can guarantee linear performance. No need to check whether a card has already been dealt or not.

Upvotes: 2

stefaanv
stefaanv

Reputation: 14392

The nested loop is only entered when kortArray[x].draget is not 1. So everytime it is 1, nothing is done and no card is assigned. First make sure you have a unique x and then in all cases update kortHand[i]

Upvotes: 2

Michel Keijzers
Michel Keijzers

Reputation: 15357

The problem still lies in the +1 for the random numbers.

Also, you are first checking in the the first assignment to x if the card is already picked, and than you assign it to an other card.

Why not use something like:

int nr_cards_picked = 0             /* Number of uniquely picked cards in hand */
/* Continue picking cards until 5 unique cards are picked. */
while (nr_cards_picked < 5) {
    x = rand() % 52;                         /* Take a random card */
    if (kortArray[x].draget == 0) {
        /* Pick this card. */
        kortArray[x].draget = 1;             /* Card is picked */
        kortHand[i]         = kortArray[x];  /* Add picked card to hand */
        nr_cards_picked++;
    }
}

Forgive compiler errors; I don't have a compiler near here.

This case you only have one time a random number call.

Theoretically it might never end but this is not likely.

Upvotes: 4

PearsonArtPhoto
PearsonArtPhoto

Reputation: 39698

A few things of note.

First of all, random number generators are not guaranteed to be random if you do a mod operation on them. Far better is to divide it out into the 52 segments, and choose like that.

Secondly, you would be far better off moving your call to generate a random number inside the while loop to the end, or just not generate one at the beginning of the for loop.

Where your problem is coming into play is that you are sometimes leaving the while loop without actually entering it, because you are randomly generating a number before you enter the loop.

Given all of this, I would do code somewhat as follows:

srand((unsigned)(time(0)));
for(i=0;i<5;i++){         
     x=-1;               
     while (kortArray[x].draget!=1){                
          x = floor(rand()*52);
      }
      printf("%i\n", x);
      kortArray[x].draget=1;
      kortHand[i]=kortArray[x];
}

Upvotes: 2

John R. Strohm
John R. Strohm

Reputation: 7667

You have:

   int x = rand()%52+1; 
      while (kortArray[x].draget!=1){                 
        x = rand()%52; 

Arrays in C are indexed starting at 0. Your first call to rand() will generate a value starting at 1. Assuming that you declared kortArray[] to hold 52 values, there is about a 2% chance that you will overrun the array.

Your first call to rand() generates values in the range 1..52. Your second call generates 0..51. ONE OF THEM IS WRONG.

Upvotes: 2

Related Questions