提问人:Faye Rauscher 提问时间:11/11/2023 最后编辑:Raymond ChenFaye Rauscher 更新时间:11/11/2023 访问量:47
使用 GDScript 的原生伪随机数生成器获得 100% 可预测的结果
100% predictable results using GDScript's native pseudo-random number generators
问:
我正在使用 GDScript(Godot 的 Python)尝试创建一种算法,该算法可以在 0 或 1 的整数之间生成 2 维数组之间的随机噪声。为此,我正在迭代预定义的变量,以将每个值附加到数组上的相关点。我知道伪随机数生成器可以揭示偏差,特别是如果在短时间内使用并以低范围定义,但即使考虑到这些因素,我似乎也得到了 100% 一致(即非随机)的结果。也就是说,数组上的每个子数组都包含完全相同的字符集,索引完全相同。
我的代码很简单:
var subMap: Array[int]
var geographyMap: Array[Array]
func generate_map():
print("Generate map function called")
var mapHeight: int = 10
var mapWidth: int = 10
geographyMap.clear()
for yy in mapHeight:
subMap.clear()
for xx in mapWidth:
var chance: int = randi_range(0, 1000)
if (chance > 500):
subMap.append(1)
else:
subMap.append(0)
geographyMap.append(subMap)
for i in geographyMap:
print(i)
结果总是这样:
example 1:
[1, 0, 0, 1, 0, 0, 1, 0, 1, 0]
[1, 0, 0, 1, 0, 0, 1, 0, 1, 0]
[1, 0, 0, 1, 0, 0, 1, 0, 1, 0]
[1, 0, 0, 1, 0, 0, 1, 0, 1, 0]
[1, 0, 0, 1, 0, 0, 1, 0, 1, 0]
[1, 0, 0, 1, 0, 0, 1, 0, 1, 0]
[1, 0, 0, 1, 0, 0, 1, 0, 1, 0]
[1, 0, 0, 1, 0, 0, 1, 0, 1, 0]
[1, 0, 0, 1, 0, 0, 1, 0, 1, 0]
[1, 0, 0, 1, 0, 0, 1, 0, 1, 0]
example 2:
[0, 1, 0, 0, 1, 0, 0, 0, 0, 0]
[0, 1, 0, 0, 1, 0, 0, 0, 0, 0]
[0, 1, 0, 0, 1, 0, 0, 0, 0, 0]
[0, 1, 0, 0, 1, 0, 0, 0, 0, 0]
[0, 1, 0, 0, 1, 0, 0, 0, 0, 0]
[0, 1, 0, 0, 1, 0, 0, 0, 0, 0]
[0, 1, 0, 0, 1, 0, 0, 0, 0, 0]
[0, 1, 0, 0, 1, 0, 0, 0, 0, 0]
[0, 1, 0, 0, 1, 0, 0, 0, 0, 0]
[0, 1, 0, 0, 1, 0, 0, 0, 0, 0]
example 3:
[1, 1, 0, 1, 1, 1, 0, 1, 1, 1]
[1, 1, 0, 1, 1, 1, 0, 1, 1, 1]
[1, 1, 0, 1, 1, 1, 0, 1, 1, 1]
[1, 1, 0, 1, 1, 1, 0, 1, 1, 1]
[1, 1, 0, 1, 1, 1, 0, 1, 1, 1]
[1, 1, 0, 1, 1, 1, 0, 1, 1, 1]
[1, 1, 0, 1, 1, 1, 0, 1, 1, 1]
[1, 1, 0, 1, 1, 1, 0, 1, 1, 1]
[1, 1, 0, 1, 1, 1, 0, 1, 1, 1]
[1, 1, 0, 1, 1, 1, 0, 1, 1, 1]
1 和 0 在单个子数组中的位置会随着每次尝试而变化,但它们每次在数组中始终匹配。当我强制函数放慢速度、每次强制它获取新种子、更改数组的尺寸或更改 rng 的范围时,这不会改变。
我用错了伪随机生成器吗?我似乎无法让这段代码生成任何实际随机的东西,只能在一个单独的子数组中生成,该模式在整个数组中重复。当然,我正在清除 subMap 数组,以确保我不会在每个元素上粘贴相同的结果或不断扩展每个元素的长度,因此它不应该是 subMap 数组未更改的结果。任何帮助使这个 rng 真正 rng 将不胜感激。
edit:包括我声明 subMap 数组的部分
编辑 2:修复了代码格式
Edit3:包含将结果打印到控制台的代码部分
编辑 4:附加上下文
注意:显然,根据 GDScript 文档,randomize() 函数(为要使用的 randi 函数生成种子)在项目现在默认运行时被调用。为了以防万一,我已经尝试了此代码的一个版本,该版本在 _ready() 中包含 randomize() 函数,但这并不能解决问题。在随机数生成器的每次迭代中调用 randomize()(无论如何文档都不建议这样做)也没有解决问题。
答:
找出问题所在。默认情况下,GDScript 中数组的 append() 函数依赖于您在参数中放置的任何值的浅拷贝。换句话说,尽管在 geographyMap 中的每个元素上清除并创建了一个新的 subMap 数组,但每次我这样做时,geographyMap 中的所有元素都会更新以匹配新的 subMap 数组。我通过调用 append() 函数中的 duplicate(true) 函数来强制深度复制来解决此问题,如下所示:
geographyMap.append(subMap.duplicate(true))
评论
randomize