在C#洗牌(Card Shuffling in C#)

2019-06-17 10:52发布

我试图写一个代码,其中列出的一副扑克牌的内容的项目,问的人有多少次想洗牌,然后洗牌他们。 它的使用方法创建使用System.Random类两个随机整数。

这些都是我的课:

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

请告诉我怎么做的人想要,然后列出洗好的牌出牌洗牌一样多。

Answer 1:

使用费雪耶茨洗牌 。

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


Answer 2:

洗牌一副扑克牌的东西,起初似乎微不足道,但通常大多数人拿出的算法不正确。

杰夫阿特伍德( 编码恐怖 )写了关于这个问题的几个很好的文章:

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

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

(尤其是第二个是一个必须读取)



Answer 3:

我想,这是你可能只是得到太多的抽象赶上了一个案例。

在软件洗牌一副牌是随机顺序提供甲板给用户的问题。 这实际上并不需要你提前洗牌它们。

INIT您的甲板上。 (I通常使用的数从1到52来表示卡和mathmatically计算哪个卡)。

  1. 通过使用随机数发生器挑一张牌出的菱扑克牌的新政一卡。
  2. 交换与一个在甲板结束该卡。
  3. 递减指着甲板上的最后一个计数器,除去从甲板卡。
  4. 转到步骤1,直到你完成绘图卡。

编辑 :而一般来说,如果你有一个好的随机数发生器没有被“洗牌”也多次获得。

这应该使用还有你的数据结构是可能的。 你只需要添加一个“画”的方法和成员变量来跟踪甲板的结束。 如果你是在实际执行的“洗牌”提前一意孤行,然后你的教授是个混蛋,B,任何时候你画52张甲板将被洗牌。 一旦你画出所有的卡,你需要提供一个“DeckEmpty”的方法,并且方法重置甲板的结束再次包括所有卡。



Answer 4:

要正确地将洗牌,你不应该只使用Random类甲板,种子只有2 ^ 32,这意味着你的Random对象可以给你2 ^ 32(假定)不同的顺序,其中有52! agencing现实生活中的甲板(阶乘52)的方式。

我使用2个GUID来创建随机数据的32字节 - > 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);
            }
        }
    }


Answer 5:

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

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

这样,你可能会得到较少的迭代更加栩栩如生洗牌



Answer 6:

洗牌应该以这种方式工作:

你把两个随机卡在甲板(在甲板上证指数是随机数)和两张卡交换位置。 例如采用索引2和卡卡在指数9和让他们换地方了。

并且可以重复一定次数。

该算法应该是这个样子:

int firstNum = rnd.Next(52);
int secondNum = rnd.Next(52);

Card tempCard = MyCards[firstNum];
MyCards[firstNum] = MyCards[secondNum];
MyCards[secondNum] = tempCard;


Answer 7:

总的来说,我会说,看看每个甲板包含卡对象的数组对象,其中每个Card对象的每个包含一个值和套房INT属性,它可以应用到值和套房的枚举,收集指定的版本每卡片的类型所使用。 (这将允许这段代码更加灵活,允许更容易比较值3 <11(插孔)!〜)你的风格会为学校项目的工作,我刚开OCD吧!

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

这是假设你使用一个底部平台类,那么它继承你想要甲板型(使它所以你可以应用此相同的代码来乌诺甲板或什么都)代号为普通型甲板类的。

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


Answer 8:

我做了一个包含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

}

}



Answer 9:

static void Shuffle(List<int> cards)
    {
        Console.WriteLine("");
        Console.WriteLine("Shuffling");
        Console.WriteLine("---------");

        cards = cards.OrderBy(x => Guid.NewGuid()).ToList();

        foreach (var card in cards)
        {
            Console.WriteLine(card.ToString());
        }
    }


文章来源: Card Shuffling in C#