C#多个实例的随机种子生成器
我在做一个简单的游戏来提高我的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(),它还是会滚相同的数字。如果我只有一名球员,那么效果很好。我该如何改进?
伪随机数发生器接种一旦在创建时。种子后,他们通过数字(基于他们的种子)按照固定的周期生成下一个数字。
当使用不带参数的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
这样他们就可以用它来推出的,而不是依靠自己的随机数发生器的霸气。
在跨类共享“随机”实例时需要注意的一件事。 'Random'不是线程安全的,所以如果你正在做多线程,你需要在'.Next'调用周围放置一个'lock(rand){...}'。 –
您的随机发生器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);
至于其他的答案指出,你的问题是你正在使用两个(相同种子)的随机数生成器,每个生成器将生成相同的序列。大约有这几个方面:
方案一:种子每个随机在不同玩家构造
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:让Random
在Player
静态
Random dice = new Random();
变化
static Random dice = new Random();
这意味着,无论多少Players
你创建,th ey会全部使用相同的Random
,避免你原来的问题。
最有可能的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);
}
你可能想让'dice'变成静态的。我猜你快速连续创建了'player1'和'player2',并且他们获得了相同的种子。 – juharr