Card Shuffling in C#
Use Fisher-Yates shuffle.
Your C# code should look something like this:
static public class FisherYates
{
static Random r = new Random();
// Based on Java code from wikipedia:
// http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
static public void Shuffle(int[] deck)
{
for (int n = deck.Length - 1; n > 0; --n)
{
int k = r.Next(n+1);
int temp = deck[n];
deck[n] = deck[k];
deck[k] = temp;
}
}
}
Shuffling a deck of cards is something that seems trivial at first, but usually the algorithm that most people come up with is incorrect.
Jeff Atwood (Coding Horror) wrote a few very good articles on the subject:
http://www.codinghorror.com/blog/archives/001008.html
http://www.codinghorror.com/blog/archives/001015.html
(especially the second one is a must-read)
I think this is a case where you may just be getting too caught up in the abstraction.
Shuffling a deck of cards in software is a matter of providing the deck to the user in a random order. This doesn't actually require you to shuffle them ahead of time.
Init your deck. (I typically use a number from 1 to 52 to represent the card and mathmatically compute which card is.)
- Deal a card by using a random number generator to pick a card out of the Deck of availible cards.
- Swap that card with the one at the end of the deck.
- Decrement a counter pointing to the end of the deck, to remove that card from the deck.
- Goto step 1 until you are done drawing cards.
Edit: And generally speaking, if you have a good random number generator nothing is gained by "Shuffling" it multiple times.
This should be possible using the data structures you've shown. You just need to add a "Draw" method, and member variable to keep track of the end of the deck. If you are hell bent on actually performing the "shuffle" ahead of time, then A your professor's a jerk, B anytime you draw 52 cards the deck will be shuffled. Once you've draw all cards, you need to provide a "DeckEmpty" method, and method to reset the End of Deck to include all cards again.
to correcly shuffle a deck you should NOT ONLY use the Random class, the seed is only 2^32 which means your Random object can give you only 2^32 (supposed) different order where there is 52! (factorial 52) way of agencing a real life deck.
i'm using 2 guid to create 32bytes of random data -> 8 seed of 4bytes and i shuffle the cards with thoses 8 different seeds
then by seed i get a certain number of cards [5,5,6,6,6,7,8,9]
here is the code i use
public void Shuffle(Guid guid1, Guid guid2)
{
int[] cardsToGet = new int[] { 5, 5, 6, 6, 6, 7, 8, 9 };
byte[] b1 = guid1.ToByteArray();
byte[] b2 = guid2.ToByteArray();
byte[] all = new byte[b1.Length + b2.Length];
Array.Copy(b1, all, b1.Length);
Array.Copy(b2, 0, all, b1.Length, b2.Length);
List<Card> cards = new List<Card>(this);
Clear();
for (int c = 0; c < cardsToGet.Length; c++)
{
int seed = BitConverter.ToInt32(all, c * 4);
Random random = new Random(seed);
for (int d = 0; d < cardsToGet[c]; d++)
{
int index = random.Next(cards.Count);
Add(cards[index]);
cards.RemoveAt(index);
}
}
}
Your Shuffle might work, but it's not really efficient and not lifelike. You should try this way:
//The shuffle goes like this: you take a portion of the deck, then put them in random places
private void Shuffle()
{
int length = DeckofCards.Count;
int level = 20; //number of shuffle iterations
List<Card> Shuffleing; //the part of the deck were putting back
Random rnd = new Random();
int PickedCount, BackPortion; //the last used random number
for (int _i = 0; _i < level; _i++)
{
PickedCount = rnd.Next(10, 30); //number of cards we pick out
Shuffleing = DeckofCards.GetRange(0, PickedCount);
DeckofCards.RemoveRange(0, PickedCount);
while (Shuffleing.Count != 0)
{
PickedCount = rnd.Next(10, DeckofCards.Count - 1); //where we place a range of cards
BackPortion = rnd.Next(1, Shuffleing.Count / 3 + 1); //the number of cards we but back in one step
DeckofCards.InsertRange(PickedCount, Shuffleing.GetRange(0, BackPortion)); //instering a range of cards
Shuffleing.RemoveRange(0, BackPortion); //we remove what we just placed back
}
}
}
This way you might get a more lifelike shuffle with less iterations