如何设计Random.Next()限制?

时间:2016-10-02 08:40:20

标签: 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);

这一切都很好,直到我决定删除1个属性。假设它是我Next()调用中的第一个属性,现在由于调用序列的移位而导致所有结果发生变化。

  • 如果我想维护其他属性的结果怎么办?

  • 我是否只生成第一个属性并丢弃它?

  • 以后如何更好地解决此问题,以便更新我的属性列表?

3 个答案:

答案 0 :(得分:3)

最明显的解决方案是生成随机值,但忽略它的结果。

另一种选择是完全摆脱Random并使用不同的随机生成算法。我想象的是具有函数f(seed, value),它返回"伪随机"值基于seedvalue,但可重复。

这样,每个属性都会与value相关联,并且它的随机等价物将独立于其他值的随机等价物。

我做的算法然后here可以用作这样的函数。如果您只使用x值,并将最后一行更改为fromto而不是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种子的组合将产生"伪随机"值范围from .. to

Generate算法可能类似于:

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范围编号的转换添加到from .. to范围。

答案 1 :(得分:1)

您可以丢弃第一个随机生成的数字,而不是生成和丢弃第一个属性。

我无法想象你将要实现的目标。如果所有属性都是随机生成的整数,为什么不将它们全部保存在List<int>类型的属性中?

答案 2 :(得分:0)

如果要保留单个对象的值,那么可能包括源中的值是最佳选项。这将使值独立于任何其他值(例如,不同的RNG实现)。

如果您为许多对象生成值(并且预生成不是一个选项),那么您当然必须丢弃每个第一个值。 可能写一个工厂功能,保持所有变化的跟踪将是最好的主意。

如果您预见到这是许多对象类的问题,您可能希望实现更通用的解决方案:例如地图fieldnumber of next calls。 但那会有点太多了,imho。