Skip to content

Instantly share code, notes, and snippets.

@Arakade
Created May 20, 2016 13:32
Show Gist options
  • Save Arakade/5fe21d3d3e9119dd78a65e676ee75eab to your computer and use it in GitHub Desktop.
Save Arakade/5fe21d3d3e9119dd78a65e676ee75eab to your computer and use it in GitHub Desktop.
A way to repeatedly randomly choose from an initially provided set of possibilities.
// Copyright Rupert Key, 2016
// Published under BSD license (commercial-friendly use as you wish but recognize owner wrote it)
using System.Collections.Generic;
// uses UnityEngine for Random.Range()
namespace UGS.Random {
/// <summary>
/// A way to repeatedly randomly choose from an initially provided set of possibilities.
/// Acts similarly to a deck of cards.
/// In much the same way that taking one card from a deck removes the possibility that that
/// card will be chosen again until the deck is reset (all cards returned and deck shuffled).
/// Use by:
/// 1. constructing with all the possibilities (<see cref="RandomGrabBag{T}"/>),
/// 2. if <see cref="hasChoicesLeft"/>
/// 3. call <see cref="chooseOne"/>
/// 4. <see cref="reset"/> to re-start with all possibilities.
/// Note: Each reset generates some garbage.
/// </summary>
/// <typeparam name="T"></typeparam>
public class RandomGrabBag<T> {
private readonly T[] choices;
private readonly List<int> choiceIndicies;
public int numEntriesTotal { get { return choices.Length; } }
/// <summary>
/// Construct with these possible choices.
/// </summary>
/// <param name="choices"></param>
public RandomGrabBag(T[] choices) {
this.choices = choices;
choiceIndicies = new List<int>();
for (int i = choices.Length - 1; i >= 0; i--) {
choiceIndicies.Add(i);
}
}
/// <summary>
/// Reset to choose from all choices again.
/// </summary>
public void reset() {
choiceIndicies.Clear();
for (int i = choices.Length - 1; i >= 0; i--) {
choiceIndicies.Add(i);
}
}
/// <summary>
/// Returns whether there are choices remaining.
/// </summary>
/// <returns>true if there are values left; else false.</returns>
public bool hasChoicesLeft() {
return 0 < choiceIndicies.Count;
}
/// <summary>
/// Get one randomly chosen value (like picking a card from the deck).
/// </summary>
/// <returns>The chosen card.</returns>
public T chooseOne() {
if (0 >= choiceIndicies.Count) {
throw new System.IndexOutOfRangeException("No choices left");
}
var chosenIndexIndex = UnityEngine.Random.Range(0, choiceIndicies.Count - 1);
var chosenIndex = choiceIndicies[chosenIndexIndex];
choiceIndicies.RemoveAt(chosenIndexIndex);
return choices[chosenIndex];
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment