Un generatore di numeri pseudo casuali (PRNG) come il Casuale
La classe in C # non è un vero generatore di numeri casuali: il suo obiettivo è approssimare la casualità con la velocità. Ciò significa che restituirà spesso una distribuzione non uniforme dei valori, che potrebbe non essere quello che desideri. In questo tutorial, ti mostrerò come risolvere questo problema con a shuffle bag.
Nota: Sebbene questo tutorial usi C #, dovresti essere in grado di utilizzare le stesse tecniche e concetti in quasi tutti gli ambienti di sviluppo di giochi.
Quando ho iniziato a creare giochi, ho usato lo standard Casuale()
metodi per creare varietà nel gameplay, creando grandi dimensioni se altro
condizioni fino a quando ho ricevuto i risultati desiderati. Se i risultati non fossero equilibrati nel modo in cui li volevo, creerei condizioni aggiuntive finché non sentissi che il gameplay era divertente. Non è stato fino a poco tempo fa ho capito che ci sono approcci migliori nel creare un'esperienza di gioco davvero divertente.
Non c'è niente di sbagliato nell'uso del built-in Casuale
classe: il problema di non ottenere i risultati desiderati deriva dall'implementazione dei metodi. In questo articolo useremo il metodo "Shuffle Bag" per fare Casuale()
si sentono più casuali (e più divertenti), usando le schede di Boggle come esempio pratico.
Hai mai notato che un'espressione come:
valore int = Random.Next (lowerBounds, upperBounds);
... ti dà una distribuzione irregolare dei numeri?
Un generatore di numeri casuali che seleziona valori compresi tra 0 e 1 non si preoccupa se restituisce tutti gli 1, quindi se hai creato un se altro
blocca usando l'espressione sopra per scegliere un ramo, probabilmente non otterrai i risultati che ti aspetti.
var rand = new Random (); per (int i = 0; i < 10; i++) Console.WriteLine(rand.Next(0, 2));
Non c'è niente di tecnicamente sbagliato Random.Next ()
, ma non garantisce una distribuzione uniforme dei numeri. Ciò significa che in molte situazioni di gioco, Casuale()
non è divertente.
Una Shuffle Bag è una tecnica per controllare la casualità per creare la distribuzione che desideriamo. L'idea è:
Implementare una Shuffle Bag in C # è semplice e la tecnica può essere facilmente convertita in qualsiasi lingua.
Poiché lo scopo di questo articolo è di concentrarsi sull'implementazione di Shuffle Bags e non sulle funzionalità linguistiche, non considereremo l'uso dei generici. Tuttavia, raccomando vivamente l'uso di generici perché ci permettono di rendere le strutture di dati di tipo sicuro senza impegnarci in tipi di dati reali. Generics ti consente di utilizzare lo stesso codice per creare Shuffle Bags che contengono molti tipi diversi di dati.Ecco il codice di base:
public class ShuffleBag private Random random = new Random (); Elenco privatodati; codice di proprietà privata; private int currentPosition = -1; private int Capacity get return data.Capacity; public int Size get return data.Count; public ShuffleBag (int initCapacity) data = new List (initCapacity);
L'inizio della classe imposta le variabili di istanza e il costruttore inizializza la variabile dell'istanza di dati sulla capacità iniziale del programmatore (ovvero quanto è grande il bagaglio con cui iniziare).
pubblico vuoto Aggiungi (elemento char, quantità int) for (int i = 0; i < amount; i++) data.Add(item); currentPosition = Size - 1;
Il Inserisci
il metodo aggiunge semplicemente il carbonizzare
a dati
tante volte quante il programmatore specifica.
Si noti che il posizione attuale
è impostato alla fine dell'elenco, poiché attraverseremo la fine più tardi. Perché dalla fine della lista? Puoi fare la traversata del Shuffle Bag dall'inizio, ma iniziare alla fine e lavorare all'indietro rende il codice più pulito.
public char Next () if (currentPosition < 1) currentPosition = Size - 1; currentItem = data[0]; return currentItem; var pos = random.Next(currentPosition); currentItem = data[pos]; data[pos] = data[currentPosition]; data[currentPosition] = currentItem; currentPosition--; return currentItem;
Il Il prossimo
il metodo è la carne di questa tecnica.
Se posizione attuale
è inferiore a uno, lo abbiamo resettato per puntare alla fine della lista e restituire il primo oggetto dalla borsa. (Questo copre la situazione in cui abbiamo attraversato tutti gli elementi e ora desidero ricominciare.)
Altrimenti, usiamo random.Next ()
scegliere un oggetto a caso dalla borsa, da qualche parte tra il primo oggetto e l'oggetto nella nostra posizione corrente. Scambiamo questo articolo selezionato casualmente con l'oggetto nella nostra posizione attuale e quindi diminuiamo posizione attuale
per 1.
Alla fine, restituiamo l'oggetto selezionato casualmente. Il risultato è che continuiamo a raccogliere oggetti che non abbiamo raccolto prima, mentre mescoliamo la borsa mentre andiamo. Ciò significa che i suoi contenuti sono in un ordine diverso quando vogliamo attraversarlo di nuovo.
Ora è il momento di provare la nostra lezione appena creata.
Diversi anni fa ho creato un clone Boggle per l'iPhone.
Un problema che ho affrontato è stato la creazione di schede dense che utilizzavano solo 16 lettere, ma ha permesso all'utente di formare centinaia di parole con quelle 16 lettere. Ho imparato a conoscere le frequenze delle lettere e come posso usarlo per creare un'esperienza utente positiva.
Usando la frequenza con cui le lettere appaiono nel testo inglese possiamo costruire un dizionario ponderato.
Dizionario statico privato letterFrequencies= nuovo dizionario 'E', 12.702, 'T', 9.056, 'A', 8.167, 'O', 7.507, 'I', 6.966, 'N', 6.769 , 'S', 6.327, 'H', 6.094, 'R', 5.987, 'D', 4.253, 'L', 4.025, 'C', 2.782, 'U', 2.758, 'M', 2.406, 'W', 2.306, 'F', 2.228, 'G', 2.015, 'Y', 1.974, ' P ', 1.929, ' B ', 1.492, ' V ', 0.978, ' K ', 0.772, ' J ', 0.153, ' X ', 0.150, ' Q ' , 0.095, 'Z', 0.074; // totale: 99,965
Nota: Q viene gestito in modo leggermente diverso rispetto alle altre lettere. Mantiene il valore dalla tabella delle frequenze delle lettere, ma appare come Qu in molti giochi di parole.
Ora possiamo creare un'istanza della nostra classe Shuffle Bag, riempire la nostra Shuffle Bag con i dati e creare folte Boggle Boards.
static void Main (string [] args) var shuffleBag = new ShuffleBag (88000); int importo = 0; foreach (var letter in letterFrequencies) amount = (int) letter.Value * 1000; shuffleBag.Add (letter.Key, amount); for (int i = 0; i < 16; i++) Console.Write(shuffleBag.Next()); Console.WriteLine();
Nota: La cosa più importante da togliere a questo pezzo di codice è il quantità
. Un moltiplicatore di 1000 restituisce risultati migliori di un moltiplicatore di 10.
Esegui i risultati attraverso un risolutore online. Quante parole trovi??
In questo articolo, abbiamo riconosciuto il problema nell'utilizzo di valori casuali con se altro
condizioni, abbiamo introdotto una soluzione utilizzando Shuffle Bags e dimostrato un utilizzo creando fitte schede Boggle. Con l'uso di Shuffle Bags prendiamo il controllo di Casuale()
metodi e creare una distribuzione uniforme dei valori che aiuti in un'esperienza di gioco positiva.