卡在C#中洗牌

我正在为一个列出一副纸牌内容的项目写一个代码,询问这个人想要洗牌多less次,然后洗牌。 它必须使用一个方法来使用System.Random类创build两个随机整数。

这些是我的课程:

Program.cs中:

namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Deck mydeck = new Deck(); foreach (Card c in mydeck.Cards) { Console.WriteLine(c); } Console.WriteLine("How Many Times Do You Want To Shuffle?"); } } } 

Deck.cs:

 namespace ConsoleApplication1 { class Deck { Card[] cards = new Card[52]; string[] numbers = new string[] { "2", "3", "4", "5", "6", "7", "8", "9", "J", "Q", "K" }; public Deck() { int i = 0; foreach(string s in numbers) { cards[i] = new Card(Suits.Clubs, s); i++; } foreach (string s in numbers) { cards[i] = new Card(Suits.Spades, s); i++; } foreach (string s in numbers) { cards[i] = new Card(Suits.Hearts, s); i++; } foreach (string s in numbers) { cards[i] = new Card(Suits.Diamonds, s); i++; } } public Card[] Cards { get { return cards; } } } } 

Enums.cs:

 namespace ConsoleApplication1 { enum Suits { Hearts, Diamonds, Spades, Clubs } } 

Card.cs:

 namespace ConsoleApplication1 { class Card { protected Suits suit; protected string cardvalue; public Card() { } public Card(Suits suit2, string cardvalue2) { suit = suit2; cardvalue = cardvalue2; } public override string ToString() { return string.Format("{0} of {1}", cardvalue, suit); } } } 

请告诉我如何使卡片洗牌尽可能多的人,然后列出洗牌。

使用Fisher-Yates shuffle 。

你的C#代码应该是这样的:

 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; } } } 

改变一副扑克牌起初看起来微不足道,但通常大多数人提出的algorithm是不正确的。

杰夫阿特伍德( 编码恐怖 )写了一些非常好的文章在这个问题上:

http://www.codinghorror.com/blog/archives/001008.html

http://www.codinghorror.com/blog/archives/001015.html

(特别是第二个是必读的)

我认为这是一个你可能会陷入抽象的情况。

在软件中刷新一副牌是一个随机的顺序向用户提供牌组的问题。 这实际上并不需要你提前洗牌。

初始化你的套牌。 (我通常使用从1到52的数字来表示卡,并用math计算哪个卡是。)

  1. 通过使用随机数发生器从卡片组中select一张卡片来处理一张卡片。
  2. 将该卡与卡组末尾的卡交换。
  3. 减less指向甲板末端的柜台,从甲板上移除该牌。
  4. 转到第1步,直到完成绘图卡。

编辑 :一般来说,如果你有一个好的随机数发生器没有什么是通过多次“Shuffling”获得的。

这应该可以使用你所显示的数据结构。 你只需要添加一个“绘制”方法,并成员variables来跟踪甲板的结束。 如果你真的想要提前实行“洗牌”,那么你的教授是一个混蛋,B任何时候你抽牌52张牌都会被洗牌。 一旦你画完了所有卡片,你需要提供一个“DeckEmpty”方法,以及重新设置卡片结束的方法来重新包含所有的卡片。

要正确地洗牌,你不应该只使用随机类,种子只有2 ^ 32,这意味着你的Random对象只能在52个地方给出2 ^ 32(假定)不同的顺序! (因子52)的方式创造一个真实的生活甲板。

我使用2 GUID创build32字节的随机数据 – > 8字节的4字节,我洗牌与8种不同的种子

然后通过种子我得到一定数量的卡[5,5,6,6,6,7,8,9]

这里是我使用的代码

  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); } } } 

你的Shuffle可能工作,但它不是真的有效,不逼真。 你应该试试这个方法:

 //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 } } } 

这样你可以用更less的迭代获得更逼真的洗牌

洗牌应该以这种方式进行:

你在牌组中有两张随机牌(牌中的牌索引是随机数)和两张牌的交换位置。 例如,在索引2处获取卡,在索引9处获取卡,并将其更换。

这可以重复一定的次数。

algorithm应该看起来像这样:

 int firstNum = rnd.Next(52); int secondNum = rnd.Next(52); Card tempCard = MyCards[firstNum]; MyCards[firstNum] = MyCards[secondNum]; MyCards[secondNum] = tempCard; 

总的来说,我会说每个卡组作为一个对象,其中包含一个Card对象数组,每个Card对象都包含一个值和套件int属性,它可以应用到值的枚举值和套件收集指定的版本为根据您使用的甲板types。 (这将允许这一点的代码是更通用的,并允许更容易的价值比较3 <11(杰克)!)你的风格将适用于一个学校项目,我只是得到它的强迫症!

 class Card { public int value { get; set; } public int suite { get; set; } } abstract class Deck { public Card[] cards { get; set; } public void ShuffleCards(int timesToShuffle) { Card temp; Random random = new Random(); // int timesToShuffle = random.Next(300, 600); #Had it setup for random shuffle int cardToShuffle1, cardToShuffle2; for (int x = 0; x < timesToShuffle; x++) { cardToShuffle1 = random.Next(this.cards.Length); cardToShuffle2 = random.Next(this.cards.Length); temp = this.cards[cardToShuffle1]; this.cards[cardToShuffle1] = this.cards[cardToShuffle2]; this.cards[cardToShuffle2] = temp; } } } 

这就是假设你使用了一个基本的Deck类,然后将它inheritance到你想要的types的甲板上(这样你就可以把这个代码应用到Uno甲板或者什么东西上。)正常types的甲板类的代码。

 class NormalDeck : Deck { // This would go in the NormalGame class to apply the enumerators to the values as a cipher. // Need int values for logic reasons (easier to work with numbers than J or K !!! // Also allows for most other methods to work with other deck<Type> (ex: Uno, Go Fish, Normal cards) public enum Suites { Hearts, Diamonds, Spades, Clover }; // Same comment as above. public enum Values { Ace, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King }; public void NewNormalDeck() { // Clear the deck of cards if (this.cards != null) { Array.Clear(this.cards, 0, this.cards.Length); } //Set Value to length of Normal deck of Cards without Jokers cards = new Card[52]; // to keep count of which card we are. int curNumofCards = 0; // Cycle through all of the suites listed in "suites" then all the values of that suite for (int x = 0; x < Enum.GetValues(typeof(Suites)).GetLength(0); x++) { for (int y = 0; y < Enum.GetValues(typeof(Values)).GetLength(0); y++) { Card newCard = new Card(); newCard.suite = x; newCard.value = y; this.cards[curNumofCards] = newCard; curNumofCards++; } } } } 

我做了一个包含7张牌的程序,然后洗牌,我希望能够帮助他们。

课程{

 static void Main(string[] args) { Random random = new Random(); var cards = new List<string>(); //CARDS VECRTOR String[] listas = new String[] { "Card 1", "Card 2", "Card 3", "Card 4", "Card 5", "Card 6", "Card 7"}; for (int i = 0; i<= cards.Count; i++) { int number = random.Next(0, 7); //Random number 0--->7 for (int j = 0; j <=6; j++) { if (cards.Contains(listas[number])) // NO REPEAT SHUFFLE { number = random.Next(0, 7); //AGAIN RANDOM } else { cards.Add(listas[number]); //ADD CARD } } } Console.WriteLine(" LIST CARDS"); foreach (var card in cards) { Console.Write(card + " ,"); } Console.WriteLine("Total Cards: "+cards.Count); //REMOVE for (int k = 0; k <=6; k++) { // salmons.RemoveAt(k); Console.WriteLine("I take the card: "+cards.ElementAt(k)); cards.RemoveAt(k); //REMOVE CARD cards.Insert(k,"Card Taken"); //REPLACE INDEX foreach (var card in cards) { Console.Write(card + " " + "\n"); } } Console.Read(); //just pause } 

}