[程式] 乱数、线性同余、perlin noise

楼主: cowbaying (是在靠北喔)   2014-10-08 13:44:34
标题打这么多是因为去年的某篇文章导致的...
除了骗还是骗
这个世界充满了欺骗...
目前还在研究乱数这东西
http://rosettacode.org/wiki/Linear_congruential_generator
有兴趣可以先阅读上面的文章
目前基本的乱数产生都是用线性同余法来达成
觉得不够乱的话就是要自己写了
方法似乎百百种
接着再阅读这篇
http://freespace.virgin.net/hugo.elias/models/m_perlin.htm
应该许多人研究过这东西
许多沙盒游戏也都是使用perlin noise来达到理论上无限大的地图
使用种子码来减少资料储存量
产生看似随机生成的世界
不过理论跟实际要使用差距蛮大的
网络上能找的资料都是很基本的东西
要实际使用还需要琢磨一番
如果照着网络上的文献来实作会发现一个范围的perlin noise的产生
跟即时产生差异还颇大的
因为还牵扯到图块接合等等问题(map tile)
需要做内插法平顺等等处理
说到这里
可以参考minecraft spigot-api里头的perlin noise
github.com/SpigotMC/Spigot-API/tree/master/src/main/java/org/bukkit/util/noise
(太长了把http截掉)
=======吃完饭之后突然忘了自己要说什么========
说点比较不容易看懂的地方
如果照着第二篇的公式来看
很快就会发现过了一定数值后结果会一直是1.0
我想这应该是同余法的极限吧
如果SEED一直不变
完全无法产生够大范围的乱数
(1.0-((x*(x*x*15731+789221)+1376312589)&7fffffff)/1073741824.0);
来分析一下上面的算式
基本上的目的就是要让1.0后面那串结果在0.0与2.0之间
这样相减才能产生正负
注意绿色的符号
那是位元运算子后面的7fffffff应该是0x7fffffff
也就是整数最大值2,147,483,647
位元运算子的用处就是确保计算后的直为正数且在该范围内
位元运算子算相当好用
接下来可以参考C或者C++的RAND与SRAND之header
在stdlib.h里
利用第一个种子码计算出下一个数值后(可能为长整数时期)
将其当成下次的种子码如此反复执行到我们指定的次数
不过这种作法我们发现每次乱数的顺序都是一样的
所以现在改善的做法都是用系统时间来当种子码(准度到秒)
不过还是有不够随机的情况产生
所以第一个种子码很重要
接下来就是我们想控制的部分了
由于PERLIN NOISE是有规律的
因此需要使用不同的频率与放大的倍率将数个阶(octave)合成起来
这边可以另外参考SIVI的作品
https://github.com/philfrei/SiVi
我目前的想法是
如果之后要带入计算的座标极大时
是否会降低运算的效能
目前还在测试
所以猜测把座标加入seed的产生
或许是个效率较高的作法
作者: LayerZ (無法如願)   2014-10-08 14:25:00
先推,不过超过我理解范围了XDD 对我而言,用时间,顶多把时间摊开来到整个活动期间都不一样就好了,根据测不准原理再去过度追求随机的随机性,因为永远无法确定玩家此时此刻抽福袋是否会合乎设计的理论..第三行前面少个不用,不用再去..唔...我发现我又再说废话了(死),可以帮我把推文删掉吗,我找时间看完再来回好了.这么方便的推文真是个糟糕的发明
作者: AmosYang (泛用人型编码器)   2014-10-08 15:22:00
作者: LayerZ (無法如願)   2014-10-08 15:25:00
楼上害我上班大笑XDDD 如果一个玩家只能骰一次,并且不能跟别人比较的话...他是成立的XDD...PS3 ESCDA Code!?

Links booklink

Contact Us: admin [ a t ] ucptt.com