1

I'm new to programming and I had to work on a program that would simulate 10,000 games of craps. I got it to calculate points for house and player just fine until I added in the function "diceRoll" where player rolls again and again until it matches the first roll or 7 (house wins). Now it gives decidedly not random results (such as the house winning 0 times out of 10,000). What did I do wrong?

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>

bool diceRoll (int a)
{
    srand( (unsigned)time(NULL));
    int n = 0;
    int b = 0;
    while(n < 1) {
        b = rand() % 12;
        if(b == a || b == 6) n++;
    }
    if(b == 6) return false;
    else return true;
}


int main (void)
{
    srand( (unsigned)time(NULL));
    int a, n, house, player, point;
    house = 0;
    player = 0;
    point = 0;

    for(n = 0; n < 10000; n++) {
        a = rand() % 12;
        if(a == 1 || a == 2 || a == 11) {
            house++;
        }
        else if(a == 6 || a == 10) {
            player++;
        }
        else {
            if(diceRoll(a) == true) player++;
            else house++;
        }
    }

    printf("The house has %i points.\n", house);
    printf("The player has %i points.\n", player);
    return 0;
}
user7116
  • 63,008
  • 17
  • 141
  • 172
Gary M
  • 167
  • 2
  • 2
  • 9
  • You've fallen into the trap of overseeding, which is just as bad as not seeding. You only have to seed a given random number generator once. – user7116 Sep 19 '13 at 21:07
  • possible duplicate of [calling rand() returning non-random results](http://stackoverflow.com/questions/9686271/calling-rand-returning-non-random-results) – user7116 Sep 19 '13 at 21:08
  • You would do well to [read this article](http://www.azillionmonkeys.com/qed/random.html) concerning why you're about to load your dice-game to a statistically non-uniform distribution due to the side effects of `rand()` - modulo weighting. Better you find out now rather than later. – WhozCraig Sep 19 '13 at 21:13

2 Answers2

2

You've over-seeded, remove the call to srand() in diceRoll and you should be fine (this ignores bias due to modulo usage).

Community
  • 1
  • 1
user7116
  • 63,008
  • 17
  • 141
  • 172
  • I updated my answer to include the link for a why modulo bias exists, stated much more eloquently than I could. – user7116 Sep 19 '13 at 21:14
  • I understand bias. I don't get overseed. – zubergu Sep 19 '13 at 21:16
  • @zubergu if you want the meat behind *why* things aren't what they may seem [see this document](http://www.azillionmonkeys.com/qed/random.html) – WhozCraig Sep 19 '13 at 21:17
  • IIRC, seeding multiple times within the same second will produce the same result over and over again. – Dakotah Hicock Sep 19 '13 at 21:22
  • 1
    @zubergu: seems backwards, but fair enough! Every time you seed a random number generator, it starts from scratch. It doesn't take long to seed it, so using `time(NULL)` as the argument would be like calling `srand(4)` in a tight loop. Constantly reseeding causes constant sorrow. – user7116 Sep 19 '13 at 21:22
  • user7116 @WhozCraig Now I get it. Put it all together in complete answer and it's a +1 from me for another lesson learned. – zubergu Sep 19 '13 at 21:24
  • @zubergu: this question is a duplicate of a question which answers it just fine. I voted to close and made my answer community wiki so I would receive no reputation. All points should go to the answerers of the original. – user7116 Sep 19 '13 at 21:26
0

Only seed in main() (and not in a loop) and don't seed it in the diceRoll(a) function.

I ran it your way and got house = 2, player = 9998.

Removing the srand((unsigned)time(null)); in the diceroll(a) came back with:

The house has 5435 points

The player has 4565 points

I assume that is what you wanted

bool diceRoll (int a)
{
    int n = 0;
    int b = 0;
    while(n < 1) {
        b = rand() % 12;
        if(b == a || b == 6) n++;
    }
    if(b == 6) return false;
    else return true;
}

int main (void)
{
    srand( (unsigned)time(NULL));
    int a, n, house, player, point;
    house = 0;
    player = 0;
    point = 0;

    for(n = 0; n < 10000; n++) {
        a = rand() % 12;
        if(a == 1 || a == 2 || a == 11) {
            house++;
        }
        else if(a == 6 || a == 10) {
            player++;
        }
        else {
            if(diceRoll(a) == true) player++;
            else house++;
        }
    }

    printf("The house has %i points.\n", house);
    printf("The player has %i points.\n", player);
    return 0;
}
Dakotah Hicock
  • 380
  • 2
  • 15