2012-09-05 191 views
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; 
     } 
    } 

} 

它不補種雖然創建隨機數。它只是輸出每個芯片的相同數字。有誰知道我可以修復它?

+0

請注意,您不需要'rand()%5'附近的圓括號。此外,該表達式產生的值從4到4,因此'死亡[5]'永遠不會被擊中。爲了避免這種錯誤,使用常量來定義面的數量(而不是硬編碼6和5),並在數組定義中使用該常量並作爲除數。 –

回答

1

srand()函數被重複調用,或者循環不好。

把你的電話打到srand()中。每個程序只能調用一次。

+0

這個答案明顯地解決了這個問題,但是並沒有很好地描述是什麼導致了這個問題。問題是'time()'返回的是相同的值,因爲它的調用速度很快,沒有足夠的時間來產生下一個時間值。如果在調用之間傳遞更多時間,那麼用於播種RNG的值以及rand()產生的值看起來會更隨機。 – bames53

+0

雖然這不會真的使用RNG生成隨機數列,但您只需從每個系列中獲取第一個值即可。這不一定與統一RNG的統計屬性相同,然後多次調用rand()來檢索由RNG生成的連續值。 – bames53

+1

我的解釋很簡短。我對此表示歉意。說這樣說有點太過於事實。實際上有些情況下你可能想要在某個已知種子或傳遞可變種子的函數中使用srand。唯一想到的就是......說你用隨機生成的關卡做了一個遊戲。您可以允許用戶將種子提供給srand,如果沒有提供,請在Linux機器上使用諸如time或/ dev/urandom之類的東西。種子比種子有更好的方式(),但是你放棄了可移植性。 –

0

你只想調用一次srand()。所以很少有時間通過​​()返回相同的值。所以隨機數發生器在同一個地方開始。

如果可能的話,在函數之前調用srand或者它的開始。

1

你只想爲你正在做的任何模擬調用srand()一次。原因是每次調用時,您都重新調整rand(),這會對rand()值施加一個偏差。如果您假設i.i.d.這一點尤其重要。

在上面的例子中,你想把srand()移出一個循環。

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