Mélange de cartes en C#

je suis en train d'écrire un code pour un projet qui liste le contenu d'un jeu de cartes, demande combien de fois la personne veut battre les cartes, puis les mélange. Il doit utiliser une méthode pour créer deux entiers aléatoires en utilisant le système.Hasard de classe.

ce sont mes classes:

programme.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?");

        }
    }
}
Pont

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


            }
        }
    }  
}

les Énumérations.cs:

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

de la Carte.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);
        }
    }
 }

s'il vous Plaît me dire comment faire les cartes shuffle autant que la personne veut et ensuite la liste des cartes déplacées.

12
demandé sur Jacob 2009-07-19 23:20:27

9 réponses

Utiliser shuffle de Fisher-Yates .

votre code C doit ressembler à quelque chose comme ceci:

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;
        }
    }
}
43
répondu hughdbrown 2009-07-19 19:58:27

mélanger un jeu de cartes est quelque chose qui semble trivial au début, mais habituellement l'algorithme que la plupart des gens viennent avec est incorrect.

Jeff Atwood ( Coding Horror ) a écrit quelques très bons articles sur le sujet:

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

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

(en particulier le deuxième est un must-read)

16
répondu Philippe Leybaert 2009-07-19 19:29:33

je pense que c'est un cas où vous peut-être simplement se laisser emporter dans l'abstraction.

aléatoire d'un jeu de cartes dans le logiciel est une question de fournir le pont de l'utilisateur dans un ordre aléatoire. Cela ne vous oblige pas à les mélanger à l'avance.

sur votre pont. (J'utilise généralement un nombre de 1 à 52 pour représenter la carte et mathmatically calculer la carte.)

  1. Affaire d'une carte par utilisation d'un générateur de nombres aléatoires pour choisir une carte dans le paquet de cartes disponibles.
  2. Échange cette carte avec celle au bout du paquet.
  3. décrémente un compteur pointant vers l'extrémité du pont, pour retirer cette carte du pont.
  4. aller à l'étape 1 jusqu'à ce que vous avez terminé le dessin des cartes.

Edit : et de manière générale, si vous avez un bon générateur de nombres aléatoires rien n'est gagné en le" mélangeant " plusieurs fois.

cela devrait être possible en utilisant les structures de données que vous avez montré. Vous avez juste besoin d'ajouter une méthode "Draw", et une variable de membre pour garder la trace de l'extrémité du deck. Si vous êtes bien décidé à effectuer le "shuffle" à l'avance, alors A votre professeur est un con, b chaque fois que vous tirez 52 cartes le jeu sera shuffled. Une fois que vous avez tiré toutes les cartes, vous devez fournir une méthode" DeckEmpty", et la méthode pour réinitialiser l'extrémité du Deck pour inclure toutes les cartes à nouveau.

5
répondu NoMoreZealots 2011-08-03 20:58:44

pour mélanger correctement un deck, vous ne devez pas seulement utiliser la classe aléatoire, la graine est seulement 2^32 ce qui signifie que votre Objet aléatoire peut vous donner seulement 2^32 (supposé) l'ordre différent où il y a 52! (factoriel 52) façon d'agencer un pont de la vie réelle.

j'utilise 2 guid pour créer 32bytes de données aléatoires - > 8 graines de 4bytes et je mélange les cartes avec ces 8 graines différentes

puis par graine je reçois un certain nombre de cartes [5,5,6,6,6,7,8,9]

voici le code que j'utilise

    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);
            }
        }
    }
3
répondu VANDERWEYEN Jonathan 2013-07-16 10:07:04

votre mélange peut fonctionner, mais ce n'est pas vraiment efficace et pas réaliste. Vous devriez essayer de cette façon:

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

de cette façon, vous pourriez obtenir un brassage plus réaliste avec moins d'itérations

2
répondu Lyozsi 2012-11-04 19:44:02

le mélange doit fonctionner de cette manière:

vous prenez deux cartes aléatoires dans le deck (l'index de la carte dans le deck est les nombres aléatoires) Et échanger les positions des deux cartes. Par exemple, prenez la carte à l'index 2 et la carte à l'index 9 et faites-les changer de place.

Et qui peut être répété un certain nombre de fois.

L'algorithme devrait ressembler à quelque chose comme ceci:

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

Card tempCard = MyCards[firstNum];
MyCards[firstNum] = MyCards[secondNum];
MyCards[secondNum] = tempCard;
-1
répondu thkala 2012-01-07 01:10:25

dans l'ensemble je dirais regarder chaque deck comme un objet qui contient un tableau d'objets de carte, que chaque objet de carte contient une valeur et une suite propriété int, qui peut être appliqué à un Enum de valeurs et suites pour rassembler la version nommée selon le Type de Deck que vous utilisez. (Cela permettrait à ce bit de code d'être plus polyvalent et permettre des comparaisons de valeur plus faciles 3 < 11 (jack) !~) Votre style de travail pour un projet scolaire, je suis juste en train de trouble obsessionnel-compulsif avec elle!

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

qui suppose que vous avez utilisé une classe de Deck de base, puis héritez-en au type de deck que vous voulez (ce qui fait que vous pouvez appliquer ce même code aux decks Uno ou ce qui plus est.) Code pour le type normal de classe de pont.

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++;
            }
        }
    }
}
-1
répondu user3342574 2014-02-23 05:47:58

j'ai fait un programme qui contient 7 cartes, puis mélanger et j'espère prendre afin de les aider.

Programme de classe

{

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

}

}

-1
répondu Diego Mauricio Guerrero 2015-05-29 20:55:47
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());
        }
    }
-1
répondu Steve 2018-07-25 14:53:52