【发布时间】:2014-09-01 01:27:19
【问题描述】:
我正在尝试生成一个随机 2D 网格,该网格是从 [x, y] 坐标按程序生成的(而不是预先生成一个 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,它应该总是给出相同的结果,无论我在程序执行期间调用它多少次。
这样做的原因是因为我正在尝试生成随机地形,这将涉及不同网格点之间的插值;用户也有可能会重新访问网格中的某个点。
它可以正确生成网格,但是我在输出中看到了很多规律:
你可以看到有一种“颗粒”,它使线在输出中对角线移动。
我正在对此进行一些研究,但在寻找方法时遇到了一些麻烦。有人知道如何让网格更加“随机”吗?
更新:感谢 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);
}
以下是它生成的一些示例网格:
【问题讨论】:
-
停止播种 get 函数。像
srand((unsigned int)time(NULL));这样的rand-seed 属于main()的顶部; once 用于该过程,除非您有意尝试重新生成相同的序列(并且在此处出现的情况并非如此)。从那开始。 (无关:如果我慢慢滚动页面 =P,这些图像可以很好地测试我的像素刷新烧毁)。 -
我在问题中添加了附加要求。如果我在流程开始时只播种一次,那么要求不成立。
-
所以你想要一些随机的,但只有一次,然后重复?在我看来,知道初始化状态并将图像存储在存储中以进行检索(即使作为
double的矩阵)将是实现这一目标的机制。或者我仍然不理解 真正的 问题(最近不太可能)。 -
如果在给定相同参数的情况下对
value_at()的两次调用必须生成相同的结果,最好不要使用系统srand()/rand(),因为这样这些函数对于其余代码将变得无用。最好使用自己的robbrit_rand()。许多互联网源代码可用于良好的 random() 函数。
标签: c random procedural-generation