序列化 java.util.Random

8
我正在开发一个小型简单游戏(主要是为了学习Java 8和JavaFX的新功能)。其中一个特性是可以种子化游戏的随机数生成器,这样你就可以在不同系统上与朋友玩大致相同的游戏(类似于Minecraft地图或The Binding of Isaac游戏)。
我想增加保存游戏以便稍后恢复的功能。查看java.util.Random类的文档后,我发现没有找到获取随机数生成器当前种子的方法。我想到的唯一恢复随机数生成器的方法是,在保存时通过反射访问种子并使用它,或者在加载时种子化初始种子并反复调用nextInt(),直到我们将随机数生成器向前滚动到保存游戏之前的位置。

2
它是“可序列化的”。这样就足够了吗? - user2357112
1个回答

6
首先,正如@user2357112所指出的,Random实现了Serializable接口,并通过写入seed字段(以及nextNextGaussianhaveNextNextGaussian字段)来实现。你尝试过简单地序列化它吗?这应该是“只需工作”™。其他序列化程序,如Gson,也可以使用。gson.fromJson(gson.toJson(r),Random.class);返回一个相同的对象。
你不一定需要相同的Random实例,只需要一个一致的实例即可。你可以简单地调用nextLong()并将该值写入你的保存文件中,例如random_seed。然后只需使用该种子初始化一个Random实例,现在从该文件加载的所有运行将表现相同。如果你想的话,甚至可以将当前正在运行的游戏中的Random实例重置为相同的种子。
另一方面,如果你正在生成地图或其他看似恒定的随机内容,并希望它在加载之间保持不变,我认为最好的方法是在开始时设置Random的种子,并像你描述的那样保存该值。为了节省计算资源,你可以将其分成比整个级别小的块。例如,将每个级别分为10份,并为每个10份使用(并保存)不同的种子。然后你只需要生成用户当前所在部分,而不是他们已经穿过的部分。如果你只保存当前状态,用户无法回到地图上之前的位置(这可能对于你的游戏来说不是问题,但一般来说不是一个好的做法)。
UX注意事项:保存游戏的随机性似乎有点过度设计。作为用户,我通常不希望保存文件保留随机性。实际上,有时玩家会利用这一点,例如如果他们在保存后遇到随机事件死亡,重新加载游戏不会立即让他们重新遇到同样的事件。我认为最好不要设置Random的种子,让每个游戏都稍微不同。

1
这将在从同一保存文件加载的游戏中产生一致的种子,但它与从早期保存文件加载并通过后来的文件保存点播放的游戏不一致。这可能很重要。 - user2357112
好的,楼上的要求可能会使我的第一个建议不可行。希望在这种情况下选项二更有意义。 - dimo414

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接