我试图生成一个从[x,y]坐标程序生成的随机2D网格(而不是预先生成一个2D数组)。原因是地图可能很大,并且很可能实际上不需要大部分网格。
这是我到目前为止所拥有的:
double value_at(Grid *grid, int seed, int x, int y) {
srand(seed + x + y * grid->width);
return (double)rand() / (RAND_MAX + 1.0);
}
更新:要求是value_at
具有参考透明度(尽可能)。所以以下内容必须成立:
int i = value_at(grid, seed, 100, 100);
int j = value_at(grid, seed, 100, 100);
assert(i == j);
换句话说,如果我使用相同的参数调用value_at
,无论我在程序执行期间调用它多少次,总是都应该给出相同的结果。
这是因为我试图生成随机地形,这将涉及不同网格点之间的插值;用户也可能会重新访问网格中的某个点。
它正确地生成了网格,但是我在输出中看到了很多规律:
你可以看到有一种" grain"发送线条通过输出对角移动。
我正在做一些研究,但我在寻找方法时遇到了一些麻烦。有没有人知道如何让网格更加随机"?
更新:感谢ldgabbay提供的链接,我添加了一个简单的旋转哈希函数,如下所示:
int simple_hash(int * is, int count) {
// this contains a bunch of arbitrarily chosen prime numbers
int i;
unsigned int hash = 80238287;
for (i = 0; i < count; i++){
hash = (hash << 4) ^ (hash >> 28) ^ (is[i] * 5449 % 130651);
}
return hash % 75327403;
}
然后value_at
函数如下所示:
double value_at(Grid *grid, int seed, int x, int y) {
int is[] = {x, y, seed};
srand(simple_hash(is, 3));
return (double)rand() / (RAND_MAX + 1.0);
}
以下是它生成的一些示例网格:
答案 0 :(得分:1)
我认为使用srand
来确定value_at
确定性是一个微妙的缺陷。通常,随机数生成器被播种一次,并且从其中出来的数字是伪随机的。但是,在这种方法中,您正在查看随机数生成器中出现的第一个随机数,用于表示不同的种子。这可能不像你想的那样随机。我希望这在很大程度上取决于系统上随机数生成器的实现。
由于您要求不能保存随机序列,我有一些想法。
1)
尝试更改用于更改随机种子的公式。现在,当您在网格中移动时,您的种子正在变得非常可预测。 (例如种子,种子+ 1,种子+ 2,......,种子+宽度,种子+宽度+ 1等)你想要的是:
srand(seed + hash(x + y * grid->width));
其中hash
是一个简单的东西,它将[0,width * height]中的数字映射到该范围内的另一个数字,但不太可预测。
可以找到一些简单的哈希函数here。
2)
在获取随机值之前,从随机数生成器中弹出确定数量的随机数。因此,在返回语句之前,添加如下行:
for (i=0; i!=skip; ++i) rand();
您可以将skip
设置为固定数字,或者甚至可以使其成为x,y甚至种子的确定性函数。