我正在圍繞程序生成,以及它和隨機生成之間的區別。我得到的區別是它是確定性的,它基於特定的種子值,就像所有的隨機引擎一樣。因此,在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
@molbdnilo基本上我不知道。因此,這個問題。我仍然對隨機數生成的工作方式感到朦朧,如果我遇到像使用短種子的池一樣的問題。 – Yann
附註:您對'distribution'的兩次調用以未指定的順序發生,因此編譯器之間的位置可能會有所不同,甚至編譯器設置也不同。如果你想要可靠的職位,在將它們傳遞給'pos'之前計算它們的值。 – molbdnilo