随机骰子不再播种

时间:2012-09-05 21:46:02

标签: c++ random srand

我创建了以下函数来为骰子游戏创建随机数

#include <iostream>
#include <ctime>
#include <cstdlib>
#include "dice.h"
#include "display.h"
using namespace std;
int die[6][10];
void dice(int times, int dice){
    int r;
    for(int x=0;x<times;x++){
        for(int x=0;x<dice;x++){
            srand(time(0));
            r=(rand() % 5);
            die[r][x]+=1;
            cout<<"Die #"<<x+1<<" rolled a "<<r<<endl;
        }
    }

}

虽然没有重新开始。它只为每个芯片输出相同的数字。有谁知道我怎么能解决它?

4 个答案:

答案 0 :(得分:3)

您没有正确使用srand和rand函数。您应该为随机数生成器“播种”一次,然后使用rand()从RNG中检索连续值。每个种子都会产生符合某些随机性标准的特定数字序列。

而是每次为随机数生成器播种,然后检索随机序列中的第一个值。由于time()被调用得如此之快以至于它返回相同的种子,因此您实际上将随机数生成器重置回相同序列的开头,因此您得到的数字与之前相同。

即使time()返回的值更新得足够快,每次都有新的种子,你仍然不能保证好的随机数。随机数生成器设计用于生成一系列数字,其中该序列具有某些统计特性。但是,无法保证相同的属性可以保留从不同的序列中选择的值。

因此,要使用确定性随机数生成器,您应该只生成一次生成器,然后使用该一个种子生成的值序列。


另一点;用于实现rand()的随机数生成器在历史上并不是很好,rand()不是可重入或线程安全的,并且将rand()生成的值转换为具有所需分布的值并不总是直截了当。

在C ++中,您应该更喜欢提供更好功能的<random>库。以下是使用<random>

的示例
#include <random>
#include <iostream>

int main() {
    const int sides = 6;
    int groups = 10, dice_per_group = 3;

    std::uniform_int_distribution<> distribution(1,sides); // create an object that uses randomness from an external source (provided later) to produces random values in the given (inclusive) range

    // create and seed the source of randomness
    std::random_device r;
    std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
    std::mt19937 engine(seed);

    for (int i=0; i<groups; ++i) {
        for (int j=0; j<dice_per_group; ++j) {
            // use the distribution with the source of randomness
            int r = distribution(engine);
            std::cout << "Die #" << j+1 << " rolled a " << r << '\n';
        }
        std::cout << '\n';
    }
}

答案 1 :(得分:1)

重复调用的函数中的srand(),或循环不好。

将你的调用放在main中的srand()。每个程序只调用一次。

答案 2 :(得分:1)

您只想为正在进行的任何模拟调用srand()一次。这样做的原因是每次调用都会重新调整rand(),这会对你的rand()值产生偏差。如果您假设i.i.d。

,这一点尤为重要

在上面的例子中,你想要将srand()移出循环。

答案 3 :(得分:0)

你只想调用一次srand()。所以很少有时间传递time()返回相同的值。所以随机数生成器从同一个地方开始。

如果可能,在函数之前调用srand,或者在函数的开头。