首先,如果您需要确保noise(x) 始终为相同的x 返回相同的值,无论如何,即使它从未被调用过,那么您根本就不能真正使用随机性。一个好的散列函数是唯一的可能性。
但是,如果您只需要能够恢复由所有先前探索过的点的值组成的先前状态(保存和加载后从未探索过的点可能会与您没有退出时不同......但是如何任何人都知道没有访问多个宇宙?),并且您不想存储所有这些点,那么重新生成它们可能是合理的。
但是,让我们后退一步。你想要一些像哈希函数一样的东西。有没有可以使用的哈希函数?
我想算法hashlib
太慢了(md5
可能是最快的,但要全部测试),但我不会在没有实际测试的情况下拒绝它们。
zlib.adler32
(or )的“随机周期”可能zlib.crc32
太短,但如果不hash
考虑它是否足够好,我不会拒绝它(可能除外)。就此而言,即使hash
加上一个不错的固定端搅拌器功能也可能足够好(至少在 64 位系统上)。
Python 没有md5
开箱即用的“介于”和“adler32”之间的任何东西。但是您可以找到数百种其他哈希算法的 PyPI 模块或源代码。就此而言,如果您熟悉任何听起来不错的特定哈希算法,那么它们中的大多数都是微不足道的——您可能可以编写一个具有 xor-folding 的FNV 哈希,所需时间比您浏览备择方案。
另外,请记住,您可以在“新游戏”时间生成一堆随机字节,将其存储在保存文件中,并将其用作哈希函数的盐。
如果您已经用尽了可能性,那么您确实需要比具有任意盐的足够快的散列函数单独给您更多的随机性,那么:
听起来您已经需要存储用户已探索的点的列表(因为您怎么知道需要恢复哪些点?)。顺序并不重要。因此,您可以按探索的顺序存储它们。这意味着您可以确定性地重新生成值(仅通过迭代列表)。这意味着您可以在自己的答案中使用@delnan 的建议。
但是,seed
不是这样做的方法。不能保证每次运行、Python 版本、机器等都将 RNG 置于相同的状态。为此,您需要setstate
:
- 保存,调用
random.getstate()
,pickle 和 stash 结果。
- 要加载、读取和取消选中状态,然后调用
random.setstate(state)
.
有关完整详细信息,请参阅文档。
如果您使用的是random.Random
实例,则完全相同,当然除了您必须先构造 arandom.Random
才能调用setstate
它。
这保证在您的程序运行之间、跨机器等之间工作。即使使用较新版本的 Python。但是,不能保证它可以与旧版本的 Python 一起使用。(也就是说,如果用户使用 Python 2.6 保存游戏,然后尝试使用 2.5 加载它,则状态将不兼容。我相信唯一的问题来自 2.6->older 和 2.3->older,但当然有不保证将来不会有其他版本。)我建议存储 Python 版本,如果它们已降级,请显示警告“此保存文件需要 Python 2.6 或更高版本。你有 Python 2.5。加载可能会失败。仍然继续吗?
这仅对模块本身有保证random.Random
(random
因为顶级模块函数只使用 hidden random.Random
)。特别是,random.SystemRandom
明确记录不工作。
实际上,您也可以random.Random
直接腌制 a ,因为状态被腌制了。看起来应该可以工作,或者腌制一个Random
对象是什么感觉?它确实有效。但实际上并没有记录它可以工作,所以getstate
为了安全起见,我会坚持腌制 .