Last active
August 29, 2015 14:19
-
-
Save noisecrime/ccf69aaabecd5109829b to your computer and use it in GitHub Desktop.
Generic Shuffle Deck
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ShuffleDeck | |
// Simple generic (mostly) deck shuffling utility. | |
using System.Collections.Generic; | |
using System; | |
public class ShuffleDeck | |
{ | |
public static Stack<T> CreateShuffledDeck<T>(IEnumerable<T> values, int numDecks) | |
{ | |
var stack = new Stack<T>(); | |
for(int l=0; l<numDecks; l++) | |
{ | |
var rand = new Random(); | |
var list = new List<T>(values); | |
while(list.Count > 0) | |
{ | |
// Get the next item at random. | |
var index = rand.Next(0, list.Count); | |
var item = list[index]; | |
// Remove the item from the list and push it to the top of the deck. | |
list.RemoveAt(index); | |
stack.Push(item); | |
} | |
} | |
return stack; | |
} | |
public static Stack<T> CreateUnshuffledDeck<T>(IEnumerable<T> values, int numDecks) | |
{ | |
var stack = new Stack<T>(); | |
var list = new List<T>(values); | |
for(int l=0; l<numDecks; l++) | |
{ | |
for(int i=0; i<list.Count; i++) | |
{ | |
stack.Push( list[list.Count - i - 1] ); | |
} | |
} | |
return stack; | |
} | |
/// <summary> | |
/// Non-Generic - shuffle deck using weights to bias results | |
/// </summary> | |
/// <returns>A shuffled (random) deck(s) with lower weight cards predominantly appearing first (or rather last due to it being a stack FILO).</returns> | |
/// <param name="values">Array of ints that represent index into card array.</param> | |
/// <param name="numDecks">Number decks.</param> | |
/// <param name="weights">Array of Weights ( values between 1 and maxWeight).</param> | |
/// <param name="maxWeight">Max weight.</param> | |
public static Stack<int> CreateShuffledDeckWeighted(int[] values, int numDecks, int[] weights, int minWeight, int maxWeight ) | |
{ | |
Stack<int> stack = new Stack<int>(); | |
Stack<int> reversestack = new Stack<int>(); | |
for(int d = 0; d < numDecks; d++) | |
{ | |
var rand = new Random(((int)UnityEngine.Time.realtimeSinceStartup) + d); | |
var list = new List<int>(values); | |
reversestack.Clear(); | |
int targetWeight = minWeight; | |
while(list.Count > 0) | |
{ | |
// Get the next item at random. | |
int index = rand.Next(0, list.Count); | |
int item = list[index]; | |
if(weights[item] > targetWeight) | |
{ | |
// Don't want this card difficulty to high | |
bool found = false; | |
int startIndex = index + 1; | |
targetWeight += 1; | |
// Loop thorugh find next suitable difficulty | |
for(int i = 0; i < list.Count; i++) | |
{ | |
index = (startIndex + i) % list.Count; | |
// We'll accept slightly harder/middle difficulty ones | |
if( weights[ list[index] ] <= targetWeight) | |
{ | |
found = true; | |
break; | |
} | |
} | |
// If nothing found use first card in list | |
if(!found) | |
{ | |
index = 0; | |
targetWeight += 1; | |
} | |
// Store the actual card index | |
item = list[index]; | |
} | |
else | |
{ | |
targetWeight -= 1; | |
} | |
if(targetWeight <= minWeight) targetWeight = minWeight; | |
if(targetWeight >= maxWeight) targetWeight = maxWeight; | |
// Remove the item from the list and push it to the top of the deck. | |
list.RemoveAt(index); | |
reversestack.Push(item); | |
} | |
// Due to using Stack reverse the order | |
while(reversestack.Count > 0) | |
{ | |
stack.Push( reversestack.Pop() ); | |
} | |
} | |
return stack; | |
} | |
public static int[] BuildIntDeck(int maxIndex) | |
{ | |
int[] thisArray = new int[maxIndex]; | |
for( int i=0; i<maxIndex; i++) | |
{ | |
thisArray[i] = i; | |
} | |
return thisArray; | |
} | |
public static void DeckTesting() | |
{ | |
Stack<int> tmpStack; | |
int numDecks = 3; | |
int numCards = 12; | |
int minWeight = 1; | |
int maxWeight = 5; | |
int[] numbers = ShuffleDeck.BuildIntDeck( numCards ); | |
int[] weights = new int[numCards]; | |
for(int i=0; i<numCards; i++) | |
{ | |
weights[i] = (i % maxWeight) + minWeight; | |
} | |
// Options | |
tmpStack = CreateUnshuffledDeck(numbers, numDecks); | |
LogAndEmptyDeck(tmpStack, numCards, "CreateUnshuffledDeck"); | |
tmpStack = CreateShuffledDeck(numbers, numDecks); | |
LogAndEmptyDeck(tmpStack, numCards, "CreateShuffledDeck"); | |
tmpStack = CreateShuffledDeckWeighted(numbers, numDecks, weights, minWeight, maxWeight); | |
LogAndEmptyDeck(tmpStack, numCards, "CreateShuffledDeckWeighted", weights); | |
} | |
public static void LogAndEmptyDeck( Stack<int> tmpStack, int numCards, string name) | |
{ | |
string str = string.Empty; | |
int counter = 0; | |
while(tmpStack.Count > 0) | |
{ | |
counter++; | |
int v = (int) tmpStack.Pop(); | |
str += v.ToString() + ((counter == numCards) ? " - " : ", "); | |
} | |
UnityEngine.Debug.Log(name + "\n" + str); | |
} | |
public static void LogAndEmptyDeck( Stack<int> tmpStack, int numCards, string name, int[] weights) | |
{ | |
string str = string.Empty; | |
int counter = 0; | |
while(tmpStack.Count > 0) | |
{ | |
counter++; | |
int v = (int) tmpStack.Pop(); | |
str += string.Format("{0} [{1}]" + ((counter == numCards) ? " - " : ", "), v.ToString(), weights[v]); | |
} | |
UnityEngine.Debug.Log(name + "\n" + str); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment