2017-04-20 78 views
0

我在做一個簡單的遊戲來提高我的C#技能。我閱讀了Random()類以及它如何從datetime生成種子,並找到了如何從一個實例獲取僞隨機生成器的一些結果。C#多個實例的隨機種子生成器

Player類:

Random dice = new Random(); 
    public int RollDice() 
    { 
     int dice1 = dice.Next(1, 7); 
     int dice2 = dice.Next(1, 7); 
     int sum = dice1 + dice2; 
     Console.WriteLine("D1: " + dice1 + " D2: " + dice2 + " SUM: " + sum); 
     return sum; 
    } 

主營:

//infiniteloop{ 
     player1.RollDice(); 
     Console.ReadKey(); 
     player2.RollDice(); 
    } 

輸出後,不再是我等待多長時間按下鍵,重新調用player2.DiceRoll(),它還是會滾相同的數字。如果我只有一名球員,那麼效果很好。我該如何改進?

+0

你可能想讓'dice'變成靜態的。我猜你快速連續創建了'player1'和'player2',並且他們獲得了相同的種子。 – juharr

回答

3

僞隨機數發生器接種一旦在創建時。種子後,他們通過數字(基於他們的種子)按照固定的週期生成下一個數字。

當使用不帶參數的Random構造函數時,當前時間用作種子。在實際生成號碼的所有後續呼叫中,當前時間不再使用,因此在這些呼叫之間等待多長時間無關緊要。

您所看到的問題是每個玩家都有自己的Random對象,並且這些對象是同時創建的。請參閱以下示例:

// these are created pretty much at the same time 
var r1 = new Random(); 
var r2 = new Random(); 


Console.WriteLine(r1.Next(1, 7)); 
Console.WriteLine(r2.Next(1, 7)); 

Console.WriteLine(r1.Next(1, 7)); 
Console.WriteLine(r2.Next(1, 7)); 

Console.WriteLine(r1.Next(1, 7)); 
Console.WriteLine(r2.Next(1, 7)); 

Console.WriteLine(r1.Next(1, 7)); 
Console.WriteLine(r2.Next(1, 7)); 

如果您運行該代碼,您將看到來自兩個隨機生成器的數字始終相同。這是因爲他們在同一時間播種。

爲了解決這個問題,您必須以不同方式對這些生成器進行種子處理,或者確保其中一個實際上正在創建之後。

然而,一個更好的解決方案是引入一個負責創建隨機擲骰子的單個對象。然後你的Player對象將使用同一個只有一個隨機數發生器的模發生器。所以隨機數將來自同一個發生器,防止它們相同。事情是這樣的:

public class DieGenerator 
{ 
    private Random rand = new Random(); 

    public int Roll() 
    { 
     return rand.Next(1, 7); 
    } 
} 

你會再創建的這個對象,並把它傳遞給Player這樣他們就可以用它來推出的,而不是依靠自己的隨機數發生器的霸氣。

+1

在跨類共享「隨機」實例時需要注意的一件事。 'Random'不是線程安全的,所以如果你正在做多線程,你需要在'.Next'調用周圍放置一個'lock(rand){...}'。 –

0

您的隨機發生器dice不會在調用player2.RollDice()時創建。在創建player2實例時創建它,我假設它是在player1的同一時間創建的,這就是爲什麼你看到相同的卷;兩個dice都有相同的種子。

要解決這個問題,一種方法是創建一個獨特的隨機生成器並將其注入Player實例中。

例如,通過構造注射應該是這樣的:

public class Player 
{ 
    private readonly Random dice; 

    public Player(Random dice) 
    { 
     Debug.Assert(dice != null); 
     this.dice = dice; 
    } 

    public int RollDice() => dice.Next(1, 7); 
} 

你會使用這樣的:

var dice = new Random(); 
var player1 = new Player(dice); 
var player2 = new Player(dice); 
0

至於其他的答案指出,你的問題是你正在使用兩個(相同種子)的隨機數生成器,每個生成器將生成相同的序列。大約有這幾個方面:

方案一:種子每個隨機在不同玩家構造

Player(int seed) { 
    this.dice = new Random(seed); 
} 

然後在main.cs

var player1 = new Player(1); 
var player2 = new Player(2); 

選項2:創建一個Random並將其傳遞給您的構造函數(或您的電話RollDice

該方法已詳述了@sdgfsdh

方案3:讓RandomPlayer靜態

Random dice = new Random();

變化

static Random dice = new Random();

這意味着,無論多少Players你創建,th ey會全部使用相同的Random,避免你原來的問題。

+0

爲什麼要引入一個'static'變量? – sdgfsdh

+0

因此,兩個'玩家'使用相同的'隨機',而不是都有自己的(相同種子)的實例。試試吧,它工作正常。 – paul

0

最有可能的dice是同時構建的兩個球員,這給他們兩個相同的種子。我會推薦給雙方球員創造一個骰子:

// Removed "Random dice = new Random(); " 

public int RollDice(Random dice) 
{ 
    int dice1 = dice.Next(1, 7); 
    int dice2 = dice.Next(1, 7); 
    int sum = dice1 + dice2; 
    Console.WriteLine("D1: " + dice1 + " D2: " + dice2 + " SUM: " + sum); 
    return sum; 
} 


// Main 
var dice = new Random(); 
while (true) 
{ 
    player1.RollDice(dice); 
    Console.ReadKey(); 
    player2.RollDice(dice); 
}