Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 随机产生的二维噪声_C_Random_Procedural Generation - Fatal编程技术网

C 随机产生的二维噪声

C 随机产生的二维噪声,c,random,procedural-generation,C,Random,Procedural Generation,我试图生成一个随机的二维网格,它是从[x,y]坐标按程序生成的(与预先生成二维数字数组相反)。这样做的原因是地图可能很大,而且很有可能实际不需要网格的大部分 以下是我目前掌握的情况: 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_具有参考

我试图生成一个随机的二维网格,它是从[x,y]坐标按程序生成的(与预先生成二维数字数组相反)。这样做的原因是地图可能很大,而且很有可能实际不需要网格的大部分

以下是我目前掌握的情况:

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_具有参考透明度(尽可能)。因此,以下观点必须成立:

int i = value_at(grid, seed, 100, 100);
int j = value_at(grid, seed, 100, 100);

assert(i == j);
换句话说,如果我用相同的参数调用
value\u 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;
}
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);
}
以下是它生成的一些示例网格:


我认为在使用
srand
使
值在
处具有确定性方面存在一个微妙的缺陷。通常,一个随机数生成器被播种一次,并且从中产生的数字是伪随机的。但是,在这种方法中,您将看到随机数生成器中为不同种子生成的第一个随机数。这可能不像您希望的那样随机。我认为这在很大程度上取决于系统上随机数生成器的实现

既然你有不能保存随机序列的要求,我有一些想法

(一)

尝试更改用于更改随机种子的公式。现在,当你在网格中移动时,你的种子会发生非常可预测的变化。(例如,seed、seed+1、seed+2、…、seed+width、seed+width+1等)您需要的是:

srand(seed + hash(x + y * grid->width));
其中,
hash
是一种简单的方法,它将[0,width*height]中的一个数字映射到该范围内的另一个数字,但不太可预测

可以找到一些简单的散列函数

(二)

在获取随机值之前,从随机数生成器中弹出一个确定数量的随机数。因此,在返回语句之前,添加一行,如:

for (i=0; i!=skip; ++i) rand();

您可以将
skip
设置为一个固定的数字,甚至可以将其设置为x、y甚至seed的确定函数。

停止对get函数进行种子设定。随机种子,类似于
srand((unsigned int)time(NULL));
属于
main()的顶部
;一次用于该过程,除非您有意尝试重新生成相同的序列(这里没有出现这种情况)。从这开始。(无关:如果我缓慢滚动页面,图像在测试像素刷新烧坏方面做得非常好=P)。我在问题中添加了一个额外的要求。如果我在过程开始时只播一次种子,则该要求不成立。因此,您想要的是随机的,但只有一次,然后是重复的?在我看来,它似乎知道初始状态,并将图像存储在存储器中以供检索(即使是作为一个双倍的
矩阵)可能是实现这一点的机制。或者我仍然不了解真正的问题(最近这不太可能)。如果两次调用
value\u at()
给定相同的参数必须生成相同的结果,最好不要使用系统
srand()/rand()
因为这些函数对于其余的代码都是无用的。最好使用你自己的
robbrit_rand()
。很多互联网源代码都可以用于好的random()函数。而不是
srand(seed+hash(x+y*grid->width));
,不会
散列(seed+x+y*grid->width))
更有意义吗?是的,也可以这样做。重点是阻止
srand
的参数是可预测的。太好了,效果很好!我最后对列表中的旋转散列函数进行了调整,加入了一些额外的大素数,直到我得到了一些看起来非常随机的参数。我将发布c在问题中。