Программа не возвращает ожидаемые результаты. Вероятно, неправильное использование bool?

Я новичок в программировании, и мне пришлось работать над программой, которая имитировала бы 10 000 игр в кости. Я получил его для подсчета очков для дома и игрока просто отлично, пока я не добавил функцию «diceRoll», где игрок бросает снова и снова, пока он не совпадет с первым броском или 7 (победа дома). Теперь он дает явно не случайные результаты (например, казино выигрывает 0 раз из 10 000). Что я сделал не так?

#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;
}

person Gary M    schedule 19.09.2013    source источник
comment
Вы попали в ловушку пересева, что так же плохо, как и отсутствие посева. Вам нужно только один раз запустить данный генератор случайных чисел.   -  person user7116    schedule 20.09.2013
comment
возможный дубликат вызова rand(), возвращающего неслучайные результаты   -  person user7116    schedule 20.09.2013
comment
Вам следует прочитать эту статью о том, почему вы собираетесь загрузить свои кости. -игра к статистически неравномерному распределению из-за побочных эффектов rand() - взвешивания по модулю. Лучше узнать сейчас, чем потом.   -  person WhozCraig    schedule 20.09.2013


Ответы (2)


Вы перевели, удалите вызов srand() в diceRoll, и все будет в порядке (это игнорирует смещение из-за использования по модулю).

person Community    schedule 19.09.2013
comment
Я обновил свой ответ, включив ссылку на то, почему существует смещение по модулю, изложенное гораздо более красноречиво, чем я мог бы. - person user7116; 20.09.2013
comment
Я понимаю предвзятость. Меня не пропускают. - person zubergu; 20.09.2013
comment
@zubergu, если вы хотите узнать правду о том, почему все не так, как может показаться см. этот документ - person WhozCraig; 20.09.2013
comment
IIRC, заполнение несколько раз в течение одной секунды будет давать один и тот же результат снова и снова. - person Dakotah Hicock; 20.09.2013
comment
@zubergu: кажется обратным, но достаточно справедливо! Каждый раз, когда вы запускаете генератор случайных чисел, он начинает с нуля. Это не займет много времени, поэтому использование time(NULL) в качестве аргумента будет похоже на вызов srand(4) в узком цикле. Постоянное пересев вызывает постоянную печаль. - person user7116; 20.09.2013
comment
user7116 @WhozCraig Теперь я понял. Соберите все это вместе в полный ответ, и это +1 от меня за еще один усвоенный урок. - person zubergu; 20.09.2013
comment
@zubergu: этот вопрос является дубликатом вопроса, который отлично на него отвечает. Я проголосовал за закрытие и сделал свой ответ вики-сообществом, чтобы не получить репутацию. Все баллы должны достаться ответчикам оригинала. - person user7116; 20.09.2013

Заполнять только в main() (а не в цикле) и не заполнять в функции diceRoll(a).

Я сделал это по-вашему и получил house = 2, player = 9998.

Удаление srand((unsigned)time(null)); в diceroll(a) вернулось с:

The house has 5435 points

The player has 4565 points

Я полагаю, это то, что вы хотели

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;
}
person Dakotah Hicock    schedule 19.09.2013
comment
Вы даете решение, не объясняя, почему было неправильно сделать это по-своему. - person qdii; 20.09.2013