生成相同的随机数?

Generating the same random number?

如何根据 xyseed 值生成相同的随机数?因此,如果您一直为 xyseed 选择完全相同的值,它总是 return 与 0.0 相同的 float1.0。类似于:

//Returns value from 0.0 to 1.0
public static float random(int seed, int x, int y) {
    ...
    return rand;
}

编辑: 我想我已经找到了可以完成这项工作的方法(抱歉,如果我问错了问题):

public static float random(int x, int y) {
    int n = x + y * 57;
    n = (n << 13) ^ n;
    return Math.abs((1.0f - ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7FFFFFFF) / 1073741824.0f));
}

Math.sin(seed + x + y)怎么样?

取决于x和y的取值范围。在您的情况下,您有两个 int,它们确实适合 Random() 种子的 long

简单的情况如下: 对于相同的 x+y,它将 return 在 0..1 范围内的相同浮点数。然而,对于不同的组合,它也可能 return 相同的浮点数。

long seed = ((long)x << 32) + y;
Random r = new Random(seed);
r.nextLong(); // discard
return r.nextFloat();

Random内部会将64bit long缩减为48bit状态。我会添加 r.nextLong() 调用只是为了确保您没有得到前几个字节 .

使用加法、异或 (^) 和与大素数的乘法的某种组合来组合 seedxy 和一些大常数得到一个随机整数。然后将此整数缩放为所需范围内的浮点数。

请注意,随机数的质量取决于这些值的精确选择。如果你想要高质量的随机数,你需要用像 Diehard 测试这样的东西来测试它们,并且 fiddle 常数直到质量足够好。

此外,由于这些操作是线性的,智能对手可能会在看到其中一些随机数后预测出您的随机数。如果这是一个问题,您应该使用一些加密算法来组合 xy 以及一个密钥。

Random class 是一个伪随机序列生成器,这意味着如果您使用相同的种子初始化它,它将 return 完全相同的序列。因此,使用您的参数组合初始化 Random 并请求一个新的浮点数。

public static float random(int seed, int x, int y) {
    long superSeed = (seed << 32) ^ (x << 16) ^ y; // combine into a single long
    return new Random(superSeed).nextFloat();
}

更新

如果我可以将您的问题解释为:"How can I always generate the same terrain from a seed (with a single new Random() call?",那么我会使用如下内容:

public static float[][] randomTerrain(long seed, int w, int h) {
    Random random = new Random(seed);
    float[][] terrainRandom = new float[w][h];
    for (int x = 0; x < w; x += 1) {
        for (int y = 0; y < h; y += 1) {
            terrainRandom[x][y] = random.nextFloat();
        }
    }
    return terrainRandom;
}

这将每次从相同的种子生成相同的随机数组。

这将随机性存储在一个数组中,但您实际上可以将其集成到您的地形生成代码中,这样您就不必在使用它之前先存储整个数组。