Meine Frage ist ziemlich allgemein. Was ist der einfachste Weg, ein RNG-System oder einen Algorithmus zu codieren, der Ergänzungen und Änderungen leicht berücksichtigt? Nehmen wir zum Beispiel an, ich habe ein RNG-System, das einen Gegenstand basierend auf dem zufälligen Wert erzeugt, der gewürfelt wird. Dann könnte eine einfache, zusammengeschlagene Lösung aussehen
if (randomNumber > 0 && randomNumber <= 0.2)
{
// spawn something
}
if (randomNumber > 0.2 && randomNumber <= 0.4)
{
// spawn some other thing
}
oder für die Chance, mehrere Gegenstände zu spawnen, vielleicht
if (randomNumber < 0.4)
{
// spawn something
}
if (randomNumber < 0.2)
{
// spawn some other thing
}
Nehmen wir an, ich füge viele, viele mögliche Gegenstände hinzu, die im Spiel erscheinen können. Es wäre mühsam, alle diese Werte zu ändern und dabei ihre relativen Raritäten usw. beizubehalten. Wie mache ich ein flexibleres RNG-System?
Antworten:
Sie können einen Algorithmus verwenden, den ich Distributed Probability RNG nenne .
Es sieht aus wie das:
Sie können wie folgt initialisieren:
Sie können Elemente erhalten, indem Sie
GetRandom(Random)
IhreExampleBucket
Instanz aufrufen .Wie funktioniert es?
Wir haben eine Liste
bucket
in derExampleBucket
Klasse benannt. Zunächst einmal ist es leer. Durch Aufrufen derAdd(Item, int)
Methode fügen SieItem
derbucket
Liste eine bestimmte Anzahl von s hinzu .Am Ende unserer
InitBucket()
Methodebucket
sieht die Liste folgendermaßen aus:Dann generieren wir einfach eine Zufallszahl zwischen
0
undbucket.Count
und geben das Element zurück, das diesem Index in derbucket
Liste entspricht.Die Wahrscheinlichkeit, ein bestimmtes Element aus einer Liste zu erhalten, beträgt
Item Count / Total Count
. Je mehr Elemente eines bestimmten Typs in der Liste enthalten sind, desto größer ist die Wahrscheinlichkeit, dass dieses Element ausgewählt wird.Also in diesem Fall;
Wenn Sie
GetRandom()
100000 Mal laufen (der Test ist hier in Fiddle ), können Sie sehen, dass die Werte den perfekten Ergebnissen ziemlich nahe kommen:Was mir an diesem Algorithmus am besten gefällt, ist, dass Sie keine Gesamtanzahl von Elementen angeben müssen. Sie können jederzeit einen beliebigen Artikel hinzufügen und müssen sich nicht um den Rest kümmern.
Wenn Sie beispielsweise die Wahrscheinlichkeit erhöhen möchten,
itemA
von der Liste zu kommen, können Sie einfach anrufenund Sie müssen nichts anderes tun.
quelle
InitBucket()
Methode ist eine Beispielverwendung, die nicht Teil des eigentlichen Codes ist. Sie sollten es auf Ihre eigene Codebasis spezialisieren. Aber es sollte nicht in derItem
Klasse sein.Gewichtete Zufälle
Anstatt mehr Kopien eines Elements in eine Liste zu schreiben, können wir stattdessen Folgendes tun:
Wir schieben diese dann in eine Liste:
Und dann bekommen wir unser Ergebnis so:
Diese Methode ist flexibler als nur das Verschieben von Elementen in eine Liste, da wir die Wrapper-Klasse dafür verantwortlich machen können, dass das Element in einen ItemStack umgewandelt und zusätzliche Daten (wie die Stapelgröße oder NBT-Daten - angewendet werden, wenn wir an Elemente in der Liste denken Minecraft erkennt, wo
Item
sich die prototypische Definition befindet undItemStack
was tatsächlich im Inventar des Spielers angezeigt wird: Größe und NBT-Daten sind nur zusätzliche Datenbits zusätzlich zur prototypischen Definition, die uns speziell über diese Gruppierung informieren, was Ihr Projekt tatsächlich hat und wie es ist vertreten liegt bei Ihnen).Dies bedeutet, dass wir mehrere zufällige Generatoren mit jeweils einer eigenen Sammlung gewichteter Listen haben können und jeder Eintrag in dieser Liste ( z. B. Äpfel) eine eindeutige Menge generieren kann, je nachdem, in welchem Generator sie sich befinden. eine Hülle wie diese:
Und anstatt
Item
in der GetRandom () -Methode zurückzukehren, kehren wir stattdessen zurückitem.GetStackFromDrop()
Wir könnten also einen Eimer für Gegenstände haben, die in einer Truhe in der Nähe einer Farm erzeugt werden, und Stapel von 1 bis 5 Äpfeln werden angezeigt, aber in einer anderen Truhe, beispielsweise in einem Minenschacht, wird immer nur 1 Apfel erzeugt, wenn ein Apfel auftaucht. Selbst wenn die Wahrscheinlichkeit für beide gleich ist, erzeugt die Truhe in der Nähe der Farm insgesamt mehr Äpfel .
quelle
Die meisten Ihrer Bedingungen sind nutzlos, wodurch Ihr Code umsonst länger wird. Dies ist die Art und Weise, wie man Dinge mit Brot und Butter macht.
Wenn Sie es noch bequemer machen möchten, können Sie es mit der Gewichtung versuchen.
Nehmen wir an, Sie haben eine Datenstruktur, die eine nimmt
Action
. Hier ist ein Pseudocode.Sie haben etwas weniger Kontrolle über den genauen Prozentsatz, aber es ist definitiv ein viel saubererer Ansatz.
quelle