2

ダイスゲームの乱数を作成するために、次の関数を作成しました

#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

4 に答える 4

3

srandおよびrand関数を正しく使用していません。乱数ジェネレーターを一度「シード」してから、を使用rand()してRNGから連続する値を取得することになっています。各シードは、特定のランダム性基準に適合する特定の数列になります。

代わりに、毎回乱数ジェネレーターをシードしてから、乱数シーケンスの最初の値を取得します。は非常に高速に呼び出されるため、同じシードが返されるためtime()、乱数ジェネレーターを同じシーケンスの先頭に効果的にリセットし、以前と同じ番号を取得します。

によって返される値がtime()更新されて毎回新しいシードを取得したとしても、適切な乱数が保証されるわけではありません。乱数ジェネレーターは、数列が特定の統計的特性を持つ数列を生成するように設計されています。ただし、同じプロパティが異なるシーケンスから選択された値を保持するという保証はありません。

したがって、決定論的乱数ジェネレーターを使用するには、ジェネレーターを1回だけシードしてから、その1つのシードによって生成された値のシーケンスを消費する必要があります。


別のポイント; 実装に使用される乱数ジェネレーターは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';
    }
}
于 2012-09-05T23:18:58.963 に答える
1

繰り返し呼び出される関数のsrand()、またはループは適切ではありません。

mainにsrand()を呼び出します。プログラムごとに1回だけ呼び出します。

于 2012-09-05T22:16:53.263 に答える
1

実行しているシミュレーションに対して、srand()を1回だけ呼び出します。この理由は、呼び出しごとにrand()を再シードするため、rand()の値にバイアスがかかるためです。これは、iidを想定している場合に特に重要です。

上記の場合、srand()をループの外に移動します。

于 2012-09-05T22:55:00.140 に答える
0

srand()を1回だけ呼び出します。そのため、time()が同じ値を返す時間はほとんどありません。したがって、乱数ジェネレーターは同じ場所から始まります。

可能であれば、関数の前、または関数の先頭でsrandを呼び出します。

于 2012-09-05T22:16:28.267 に答える