2017-04-20 81 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); 
}