C# 如何围绕Random.Next()限制进行设计?
假设我有一个具有10个属性的对象,所有属性都是基于C# 如何围绕Random.Next()限制进行设计?,c#,unity3d,C#,Unity3d,假设我有一个具有10个属性的对象,所有属性都是基于System.Random的算法使用预先确定的种子随机生成的,例如: System.Random randomNumber = new System.Random(seed); int prop0 = randomNumber.Next(x0, y0); int prop1 = randomNumber.Next(x1, y1); //... int prop9 = randomNumber.Next(x9, y9); 这一切都很好,直到我决定
System.Random
的算法使用预先确定的种子随机生成的,例如:
System.Random randomNumber = new System.Random(seed);
int prop0 = randomNumber.Next(x0, y0);
int prop1 = randomNumber.Next(x1, y1);
//...
int prop9 = randomNumber.Next(x9, y9);
这一切都很好,直到我决定删除1个属性。假设它是我调用Next()
的第一个属性,现在所有结果都会因调用顺序的改变而改变
- 如果要维护其他属性的结果,该怎么办
- 我是否只生成第一个属性并丢弃它
- 我以后应该如何最好地解决这个问题,以便更轻松地更新我的属性列表?
我无法想象你会取得什么成就。如果所有属性都是随机生成的整数,为什么不将它们一起保存在
列表
?类型的属性中?如果要保留单个对象的值,那么最好的选择可能是在源中包含这些值。这将使这些值独立于任何其他值(例如,不同的RNG实现)
如果您为许多对象生成值(并且预生成不是选项),那么您肯定必须放弃第一个值。
也许编写一个工厂函数来跟踪所有更改是最好的主意
如果您预见到这是许多对象类的一个问题,那么您可能需要实现一个更通用的解决方案:例如,将字段
映射到下一次调用的次数
。
但是这有点太多了,imho。最明显的解决方案是生成随机值,但忽略它的结果 另一个选择是完全摆脱
随机
,使用不同的随机生成算法。我想象的是函数f(seed,value)
,它基于seed
和value
返回“伪随机”值,但它是可重复的
这样,每个属性都将有与其关联的值
,并且它的随机等价物将独立于其他值的随机等价物
我当时做的算法可以用作这样的函数。如果只使用x值,将最后一行从更改为,并将更改为,而不是将0
更改为3
,则可以像这样使用它:
int prop0 = RandomX.Generate(seed, 0x45F6C854, x0, y0);
int prop1 = RandomX.Generate(seed, 0x96F4DC41, x1, y1);
//...
int prop9 = RandomX.Generate(seed, 0xFE840301, x9, y9);
因此,如果删除或添加属性,它不会影响其他属性。如果您在代码中生成所有的数字,这也会起作用,因此您不必对每个值的生成进行监视
或者你可以用类似的东西
int prop0 = RandomX.Generate(globalSeed, objectSeed, propertySeed, from, to);
3个种子的组合将在
到
的范围内产生“伪随机”值<代码>至
生成算法可能类似于:
public static uint bitRotate(uint x)
{
const int bits = 16;
return (x << bits) | (x >> (32 - bits));
}
public static UInt32 Generate(int seed1, int seed2, int seed3)
{
// simple "hashing" algorithm
UInt32 num = 1;
for (uint i = 0; i < 16; i++)
{
// multiply by prime numbers
num = num * 119 + (uint)seed1;
num = bitRotate(num);
num = num * 541 + (uint)seed2;
num = bitRotate(num);
num = num * 809 + (uint)seed3;
num = bitRotate(num);
num = num * 673 + (uint)i; // not sure if necessary
num = bitRotate(num);
}
return num;
}
公共静态uint位旋转(uint x)
{
常数int位=16;
返回(x>(32位));
}
公共静态UInt32生成(int-seed1、int-seed2、int-seed3)
{
//简单的“散列”算法
UInt32 num=1;
对于(uint i=0;i<16;i++)
{
//乘素数
num=num*119+(uint)种子1;
num=位旋转(num);
num=num*541+(uint)种子2;
num=位旋转(num);
num=num*809+(uint)种子3;
num=位旋转(num);
num=num*673+(uint)i;//不确定是否需要
num=位旋转(num);
}
返回num;
}
只需将fulluint
范围编号转换为from
<代码>到范围。我很难想象你想做什么。这些属性看起来像什么?你如何分配他们的价值?“由于调用顺序改变而导致的结果变化”是什么意思?请阅读并展示你的代码。是的,想象你期望发生的事情真的很复杂。当您删除一个属性时,您预计会发生什么情况?如果我删除Next()
的第一行,之后所有的值都会移动(我知道这是一个没有上下文的混淆词)。我希望能够运行这个程序,并获得与prop1-9相同的结果。当然,只有一种可能的解决方案(运行Next()
但放弃它),但我想设计我的程序来期望它,所以我不会到处乱扔Next()
。你的算法看起来很酷,让我想起了xxhash(我用它来散列种子,以避免在第1-n个种子上重复模式)。但我不确定你的算法在第1个种子上的随机性有多大?你说的“第1个种子”是什么意思?我的意思是有2级随机性。(1) 就使用单个种子和获取第1个Next()
而言。(2) 使用1-n作为种子值,并为每个种子值取1stNext()
。我更大的要求包括两者。所以我最终做了System.Random(散列(种子))
作为System.Random
不符合第二个要求。无论如何,我认为这不是我最初问题的重点。你能解释一下RandomX.Generate(seed,0x45F6C854,x0,y0)
,或者它与类似的散列函数有何不同?@bitinn如果你不确定,你不应该接受这个答案。这可能会阻止其他人尝试回答。