Card Shuffling in C#

2019-01-01 09:32发布

I am trying to write a code for a project that lists the contents of a deck of cards, asks how much times the person wants to shuffle the deck, and then shuffles them. It has to use a method to create two random integers using the System.Random class.

These are my classes:

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

Please tell me how to make the cards shuffle as much as the person wants and then list the shuffled cards.

9条回答
柔情千种
2楼-- · 2019-01-01 09:45

I made a program that contains 7 cards, then shuffle and I hope to take in order to help them.

class Program {

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

}

}

查看更多
一个人的天荒地老
3楼-- · 2019-01-01 09:46
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());
        }
    }
查看更多
宁负流年不负卿
4楼-- · 2019-01-01 09:47

Overall I'd say look at each deck as an object which contains an array of Card objects, which each Card object each contains a value and suite int property, which can be applied to an Enum of values and suites to gather the named version as per the Type of Deck you are using. (This would allow this bit of code to be more versatile and allow easier value comparisons 3 < 11 (jack) !~) Your style will work for a school project, I am just getting OCD with it!

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

That is assuming that you used a base Deck class, then inherit it to the type of deck you want (making it so you can apply this same code to Uno decks or what ever.) Code for normal type of deck class.

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++;
            }
        }
    }
}
查看更多
弹指情弦暗扣
5楼-- · 2019-01-01 09:48

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);
            }
        }
    }
查看更多
孤独总比滥情好
6楼-- · 2019-01-01 09:50

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.)

  1. Deal a card by using a random number generator to pick a card out of the Deck of availible cards.
  2. Swap that card with the one at the end of the deck.
  3. Decrement a counter pointing to the end of the deck, to remove that card from the deck.
  4. 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.

查看更多
宁负流年不负卿
7楼-- · 2019-01-01 10:01

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;
        }
    }
}
查看更多
登录 后发表回答