Skip to content

Instantly share code, notes, and snippets.

@mstevenson
Last active May 25, 2020 12:16
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save mstevenson/4050130 to your computer and use it in GitHub Desktop.
Save mstevenson/4050130 to your computer and use it in GitHub Desktop.
Shuffle bag algorithm implemented in C#
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class ShuffleBag<T> : ICollection<T>, IList<T>
{
private List<T> data = new List<T> ();
private int cursor = 0;
private T last;
public T Next ()
{
if (cursor < 1) {
cursor = data.Count - 1;
if (data.Count < 1)
return default(T);
return data[0];
}
int grab = Mathf.FloorToInt (Random.value * (cursor + 1));
T temp = data[grab];
data[grab] = this.data[this.cursor];
data[cursor] = temp;
cursor--;
return temp;
}
#region IList[T] implementation
public int IndexOf (T item)
{
return data.IndexOf (item);
}
public void Insert (int index, T item)
{
data.Insert (index, item);
}
public void RemoveAt (int index)
{
data.RemoveAt (index);
}
public T this[int index] {
get {
return data [index];
}
set {
data [index] = value;
}
}
#endregion
#region IEnumerable[T] implementation
IEnumerator<T> IEnumerable<T>.GetEnumerator ()
{
return data.GetEnumerator ();
}
#endregion
#region ICollection[T] implementation
public void Add (T item)
{
Debug.Log (item);
data.Add (item);
cursor = data.Count - 1;
}
public int Count {
get {
return data.Count;
}
}
public void Clear ()
{
data.Clear ();
}
public bool Contains (T item)
{
return data.Contains (item);
}
public void CopyTo (T[] array, int arrayIndex)
{
foreach (T item in data) {
array.SetValue (item, arrayIndex);
arrayIndex = arrayIndex + 1;
}
}
public bool Remove (T item)
{
return data.Remove (item);
}
public bool IsReadOnly {
get {
return false;
}
}
#endregion
#region IEnumerable implementation
IEnumerator IEnumerable.GetEnumerator ()
{
return data.GetEnumerator ();
}
#endregion
}
@col000r
Copy link

col000r commented Sep 22, 2013

Love it!

@col000r
Copy link

col000r commented Sep 22, 2013

I found a problem! Have a look at this code:

    void Start () {
        ShuffleBag<int> intBag = new ShuffleBag<int>();
        for (int i = 0; i < 4; i++) {
            intBag.Add(i);
        }

        intBag.Remove(3);

        for (int x = 0; x < 10; x++) {
            for (int y = 0; y < intBag.Count; y++) {
                Debug.Log ("Shufflebag: " + intBag.Next());
            }
            Debug.Log ("---");
        }
    }

I create a ShuffleBag with 4 values, remove one value and then I try to go through the entire bag several times...
This throws an Error on line 20.

To fix this for Remove, RemoveAt and Insert I had to set the cursor to data.Count -2 in Remove/RemoveAt and to data.Count in Insert...

Made a fork and fixed it: https://gist.github.com/col000r/6658520

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment