WeightedRandomizer

Author: Edgar Neto

Description
This class provides a way to retrieve a random element from a collection, where elements have different weights (different chances of being spawned)

Usage
Example:

For this example to work we assume that weights is a Dictionary that contains the spawn rates. Example:

Limitations
Please keep in mind that, for this to work in iOS environment, the type used as the key of the Dictionary (in the example above, the  Animal  class) cannot be a Reference type (i.e., Class), it must be a Value type (i.e., Struct). This happens because the AOT compiler does not support Reference types as Generic Type Arguments for dictionary keys.

Code
///    ///     public static class WeightedRandomizer {       public static WeightedRandomizer From(Dictionary spawnRate) {           return new WeightedRandomizer(spawnRate); }   }

public class WeightedRandomizer {       private static Random _random = new Random; private Dictionary _weights; ///        /// Instead of calling this constructor directly, /// consider calling a static method on the WeightedRandomizer (non-generic) class /// for a more readable method call, i.e.: ///        ///          ///         ///         ///          public WeightedRandomizer(Dictionary weights) {           _weights = weights; }

///        /// Randomizes one item ///        /// An ordered list withe the current spawn rates. The list will be updated so that selected items will have a smaller chance of being repeated. /// The randomized item. public T TakeOne {           // Sorts the spawn rate list var sortedSpawnRate = Sort(_weights);

// Sums all spawn rates int sum = 0; foreach (var spawn in _weights) {               sum += spawn.Value; }

// Randomizes a number from Zero to Sum int roll = _random.Next(0, sum);

// Finds chosen item based on spawn rate T selected = sortedSpawnRate[sortedSpawnRate.Count - 1].Key; foreach (var spawn in sortedSpawnRate) {               if (roll < spawn.Value) {                   selected = spawn.Key; break; }               roll -= spawn.Value; }

// Returns the selected item return selected; }

private List> Sort(Dictionary weights) {           var list = new List>(weights);

// Sorts the Spawn Rate List for randomization later list.Sort(               delegate(KeyValuePair firstPair, KeyValuePair nextPair)               {                    return firstPair.Value.CompareTo(nextPair.Value);                }             );

return list; }   }