我一直在研究 perlin 脚本,但在创建简单的伪随机值时遇到了问题。
我需要能够从 xy 坐标创建种子值,但 x+y 在重复值方面存在明显问题。他们也进入负空间,所以 x^y 不起作用。
抱歉,如果这已经在其他地方得到了回答,但我不明白或找不到。
您想为每个 x,y 对分配一个可重复的随机数吗?
使用 x,y 的线性或一般函数组合作为种子将在分布中产生伪影(至少如果您不使用非常复杂的函数)。试试这个,我遇到了同样的问题,它对我有用
//seeded random for JS - integer
function irnd2()
{
a=1664525;
c=1013904223;
m=4294967296;
rnd2.r=(rnd2.r*a+c)%m;
return rnd2.r;
}
//seeded random for JS - double [0,1]
function rnd2()
{
a=1664525;
c=1013904223;
m=4294967296;
rnd2.r=(rnd2.r*a+c)%m;
return rnd2.r/m;
}
rnd2.r=192837463;
//seed function
function seed2(s)
{
s=s>0?s:-s;
rnd2.r=192837463^s;
}
//my smart seed from 2 integer
function myseed(x,y)
{
seed2(x);//x is integer
var sx=irnd2();//sx is integer
seed2(y);//y is integer
var sy=irnd2();//sy is integer
seed2(sx^sy);//using binary xor you won't lose information
}
为了使用它:
myseed(x,y);
irnd2();
通过这种方式,您可以获得良好的不相关随机序列。
我在 JS 中使用它,但它也应该在其他语言中工作,假设种子的参数和 rnd 的返回值是一个整数。
取两者的绝对值x
和y
第一;然后x^y
会正常工作。创建伪随机源的最简单方法之一是使用时间。您可以尝试乘以x^y
当前系统时间;此方法生成重复种子值的机会极低。
如果您知道您拥有的值的范围,您可以简单地将 x 和 y 转换为用零填充的字符串,附加两个字符串,然后通过哈希函数运行生成的字符串。
您需要更好地定义问题以获得最佳答案。
如果您的 x 和 y 值相对较小,您可以将它们放入整数的高位和低位部分(您的语言中的种子是整数),例如对于 32 位平台:
int 种子 = x << 16 + y;
如果种子值不允许为负(我没有完全理解你的问题中的“负空间”是什么意思,无论你是指地理还是种子值),你可以取种子的绝对值.
如果您的意思是坐标可以具有负值,那么您的最佳行动方案取决于您是否想要相同的坐标种子和相反的种子。
在 C# 中,根据 alexroat 的回答进行了改编和改进。只需设置Random.seed = MyUtils.GetSeedXY(x, y)
,您就可以开始了。
public static class MyUtils
{
static int seed2(int _s)
{
var s = 192837463 ^ System.Math.Abs(_s);
var a = 1664525;
var c = 1013904223;
var m = 4294967296;
return (int) ((s * a + c) % m);
}
public static int GetSeedXY(int x, int y)
{
int sx = seed2(x * 1947);
int sy = seed2(y * 2904);
return seed2(sx ^ sy);
}
}