你如何在C#中获得Random的当前种子?

在我的游戏中,我将使用随机值来选择玩家从胸部获得的奖励。 问题是你可以快速保存并快速加载,这意味着他们可以继续重新加载以重新随机化,直到他们得到他们想要的东西。 有没有办法让我可以获取我的Random对象的当前种子值,并在加载时可能返回到同一点,这样他们就不会滥用随机化?

获取种子时不确定,但您可以保存您为Random对象赋予的值。 请记住,有两个构造函数。 第二个是Random(Int32) ,所以如果你自己设置种子(一个足够简单的值是System.DateTime.Now.Millisecond ),你可以在将它传递给构造函数之前将其存储在某处。 如果您尚未阅读,请查看MSDN文档, url为http://msdn.microsoft.com/en-us/library/system.random.aspx 。

这是不可能的。

相反,您可以使用二进制序列化序列化Random实例。
Random[Serializable] ,种子和内部状态将持续存在。

但请注意,保存随机种子可让您的玩家预测未来,如果您允许在战斗中保存,这非常有用。

另请注意,用户仍然可以保存,打开胸部,加载,执行生成随机数的动作,然后从胸部获取不同的项目。

这只与切线有关,但是如果有人想知道为什么Random没有名为Seed的属性或者叫做GetSeed()的方法,我愿意下注这可能是出于安全问题:你想要吗?将“随机”数字生成器的内部工作暴露给外界? 绝对不! 否则,一些客户端代码可能会四处寻找,直到它获得您正在使用的值,然后使用它们执行令人讨厌和无意义的事情。

实际上, 没有存储 Seed因为它与初始化后的算法无关。 它的一个衍生物mj存储在SeedArray ,你可以检查使用Reflection来比较两个Random实例:

 int subtraction = (Seed == Int32.MinValue) ? Int32.MaxValue : Math.Abs(Seed); mj = MSEED - subtraction; SeedArray[55]=mj; 

所以你要做的就是检查SeedArray的最后一个元素(索引55)。 这是Seed唯一使用的地方。

[从已删除的问题中移出答案如何确定两个Random实例是否具有相同的种子? ]

我可能只是按照MSDN使用它: http : //msdn.microsoft.com/en-us/library/ctssatww.aspx

 Random(seed) 

种子是一些价值我从存储装载。

您可以将随机奖励计算为以下哈希函数:

  1. 开始游戏时分配的种子,并保存在已保存的游戏中; 和
  2. 胸部的一些恒定属性,在所有游戏中都是不变的(例如,固定的ID,或者如果它从未移动的话,它的位置)。

这种方法的优点是,无论您保存和重放多少次,给定的胸部总会在给定的游戏中产生相同的奖励,即使在不同的顺序打开胸部,或者在不同的顺序中触发其他“随机”事件。 此外,每个胸部的奖励都独立于其他胸部的奖励,只要哈希中使用的胸部属性是独立的。

在以下示例中, GetRewardId生成奖励ID作为与胸部的x坐标异或的游戏种子的散列。 它使用Random来执行散列,使用散列输入作为Random对象的种子,并将第一个随机生成的数字作为输出。

 private static int GetRewardId(int seed, float coord, int numRewards) { int tempSeed = BitConverter.ToInt32(BitConverter.GetBytes(coord), 0) ^ seed; return new Random(tempSeed).Next(numRewards); } int seed = new Random().Next(); int numDifferentRewards = 5; float xCoordinate = chest.Position.X; int rewardId = GetRewardId(seed, xCoordinate, numDifferentRewards); 

如果您的许多箱子可能在sace中对齐,您可能想要选择不同的属性,或使用其他尺寸,也可以使用y和/或z坐标进行异或。

不幸的是,在Microsoft的参考实现中,甚至没有保存no arg ctor的种子值,更不用说暴露访问了: http : //referencesource.microsoft.com/#mscorlib/system/random.cs,bb77e610694e64ca

但是,您也可以在参考实现中看到,您可以传入的值(可能应该 – 我知道我这样做),就像它们一样,是: Environment.TickCount

所以将它保存到变量中,然后将该变量传递给带有arg的ctor,你现在知道了种子。 事实并非如此,但无论您的意图是什么,这都应该足够了。

我建议你生成一个随机数,并将其用作真实随机数生成器的种子数。 通过此方法,您有一个实际上是随机数的种子编号,您可以保存种子编号以供进一步使用。