【问题标题】:How is a typable seed generated for procedural generation?如何为程序生成生成可类型化的种子?
【发布时间】:2016-07-05 09:56:19
【问题描述】:

我正在研究程序生成,以及它与随机生成之间的区别。我知道不同之处在于它是确定性的,它基于特定的种子值,就像所有随机引擎一样。

所以在 C++11 中,我知道要获得“最佳”随机序列,应该使用 std::seed_seq,它不需要加密安全,所以 std::mt19937 就可以了。

在这种情况下,我想要世界上物体的一堆位置,这样我就可以生成一个关卡,然后我想给我的朋友发短信这个全新关卡的种子,因为它真的很酷。但事实上,输入189151022 140947902 1454660100 853918093 3243866855 真的很烦人。那么作为开发人员,我可以做些什么来确保随机性得到保留并具有更多的类型能力?

我认为将值散列为字符串,然后将其反转,(但后来我记得散列的意义)或者只是使用散列本身,但作为种子会更糟吗?或者它甚至有什么关系,我可以只使用“lol”作为我的种子,让它和一个兆字节长的完美随机数一样好吗?

这是我为帮助我更好地理解它而制作的快速示例。

#include <iostream>
#include <random>
#include <array>

using std::cout;
using std::endl;
using std::array;

struct pos
{
    float x, y;
    pos(float x, float y) : x(x), y(y) {}

    void print()
    {
        cout << "(" << x << " " << y << ")" << endl;
    }
};

int main()
{
    //Get seed
    std::random_device rd;
    array<unsigned long, 5> seed = { rd(), rd(), rd(), rd(), rd() };

    //Seed generator
    std::mt19937 generator;
    generator.seed(std::seed_seq(seed.begin(), seed.end()));

    //Setup distribution
    std::uniform_real_distribution<float> distribution(0, 100);

    //Generate the world (or whatever)
    pos a = pos(distribution(generator), distribution(generator));
    pos b = pos(distribution(generator), distribution(generator));
    pos c = pos(distribution(generator), distribution(generator));
    //And many, many more calls to get values from the generator

    a.print();
    b.print();
    c.print();

    //For when I want the same world back
    cout << "Seed: ";
    for (unsigned long s : seed)
    {
        cout << s << " ";
    }
    cout << endl;
}

要清楚,我要问的问题是:

我应该在游戏环境中的程序生成器中使用什么作为种子,以这种方式进行操作有什么好处和坏处?

【问题讨论】:

  • 在游戏中通常没有必要使用“花哨”的随机数。您是否尝试过使用普通的 32 位种子(四个十六进制数字,非常可文本)并得出结论认为它不够好? (最适合您的游戏的“最佳”RNG 是最适合您的,不一定是具有“最佳随机性”的那种。)
  • @molbdnilo 我不知道,基本上。因此问题。我仍然对随机数生成的工作原理以及是否会遇到诸如仅使用短种子的池耗尽之类的问题感到困惑。
  • 附带说明:您对distribution 的两次调用以未指定的顺序发生,因此位置可能因编译器甚至编译器设置而异。如果您想要可靠的位置,请在将它们传递给 pos 之前计算它们的值。
  • @molbdnilo 很公平,我会记住这一点,但代码更多的是作为示例而不是我使用的东西。但除此之外,我很乐意接受您第一条评论的引用版本作为答案。
  • 如果您不知道,“可能工作的最简单的事情”是一个很好的起点。只需抽象出 RNG 细节,以便您可以轻松地交换实际的生成器。审美和享受比数学严谨更重要。 (我没有发布任何答案,因为我认为除了“从简单开始,尝试一些东西,看看会发生什么,然后从那里得到它”之外,没有其他答案了。)

标签: c++ c++11 random procedural-generation


【解决方案1】:

从生成的足够长的字符串开始(例如“gorgeous house”)。

通过散列将其转换为数字(足以用于随机种子)。 可以使用string characters and their position获取哈希。

如果您在另一边使用相同的哈希函数,您的朋友应该能够使用相同的文本并获得相同的数字(相同的种子!)。

【讨论】:

    【解决方案2】:

    将种子设为字符串值。要从字符串中获取要使用的数字,请对其进行哈希处理,例如 sha256

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-15
      • 1970-01-01
      • 2011-09-09
      • 1970-01-01
      相关资源
      最近更新 更多