2016-07-05 11 views
1

Ich wickle meinen Kopf herum prozedurale Erzeugung und den Unterschied zwischen ihm und zufälliger Erzeugung. Ich verstehe, dass der Unterschied darin liegt, dass es deterministisch ist und auf einem bestimmten Seed-Wert basiert, wie es bei allen Zufallsmaschinen der Fall ist.Wie wird ein typisierbarer Seed für die prozedurale Generierung generiert?

So in C++ 11, verstehe ich, dass die ‚besten‘ Zufallssequenzen zu bekommen, ein std::seed_seq verwendet werden soll, und es muss nicht kryptographisch sicher sein, also ein std::mt19937 in Ordnung ist.

In diesem Szenario möchte ich eine Reihe von Positionen für Objekte in der Welt, so dass ich ein Level generieren kann, und dann möchte ich meinen Freund den Samen dieses brandneuen Level, weil es wirklich cool war. Aber so wie es ist, ist Tippen 189151022 140947902 1454660100 853918093 3243866855 wirklich ärgerlich. Also was kann ich als Entwickler tun, um sicherzustellen, dass die Zufälligkeit mit etwas mehr Typ-Fähigkeit erhalten bleibt?

Ich dachte, Hash-Werte als Zeichenfolge und dann umzukehren, (aber dann erinnerte ich mich an den Punkt der Hashes) oder einfach den Hash selbst verwenden, aber wäre das als Samen schlechter? Oder spielt es überhaupt eine Rolle, und kann ich einfach "lol" als meinen Seed verwenden und das ist genau so gut wie eine Megabyte lange perfekte Zufallszahl?

Hier ist das schnelle Beispiel, das ich gemacht habe, um mir zu helfen, es ein bisschen besser zu verstehen.

#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; 
} 

Um klar zu sein, die Frage ich frage ist:

Was in einem Verfahrensgenerator für einen Samen sollte ich in einem Spiel Kontext verwenden, und was sind die Vor- und Nachteile, es zu tun in diese Mode?

+1

In Spielen ist es normalerweise nicht nötig, "ausgefallene" Zufallszahlen zu verwenden. Haben Sie versucht, einen einfachen 32-Bit-Seed (vier hexadezimale Ziffern, sehr textfähig) zu verwenden und daraus geschlossen, dass es nicht gut genug ist? (Der "beste" Zufallsgenerator für Ihr Spiel ist derjenige, der am besten für Sie funktioniert, und das ist nicht unbedingt der mit "bester Zufälligkeit".) – molbdnilo

+0

@molbdnilo Ich weiß es nicht, im Grunde. Daher die Frage. Ich bin immer noch unklar, wie die Generierung von Zufallszahlen funktioniert, und wenn ich auf Probleme stoßen würde, dass der Pool knapp wird, verwende ich nur einen kurzen Seed. – Yann

+1

Nebenbei bemerkt: Ihre beiden Aufrufe von 'distribution' erfolgen in einer nicht angegebenen Reihenfolge, so dass die Positionen zwischen Compilern und sogar mit Compiler-Einstellungen variieren können. Wenn Sie zuverlässige Positionen wünschen, berechnen Sie deren Werte, bevor Sie sie an "pos" übergeben. – molbdnilo

Antwort

-1

machen Sie den Seed einen String-Wert. Um die Nummer aus der Zeichenkette zu erhalten, nehmen Sie einen Hashwert wie sha256

1

Beginnen Sie mit einer ausreichend langen generierten Zeichenkette (wie 'gorgeous house').

Konvertieren Sie es in eine Zahl (genug für zufälligen Seed), indem Sie es hashen. Ein Hash kann mit der string characters and their position erhalten werden.

Wenn Sie die gleiche Hash-Funktion auf der anderen Seite verwenden, sollte Ihr Freund in der Lage sein, den gleichen Text zu verwenden und die gleiche Nummer zu erhalten (gleicher Startwert!).