2009-07-19 169 views
13

Estoy tratando de escribir un código para un proyecto que enumera el contenido de un mazo de cartas, pregunta cuántas veces quiere barajar el mazo y luego las mezcla. Tiene que usar un método para crear dos enteros aleatorios usando la clase System.Random.Barajar cartas en C#

Estos son mis clases:

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

Dígame cómo hacer que las cartas se mezclen tanto como quiera la persona y luego enumere las cartas barajadas.

+0

Fija el formato para usted. –

+2

Pregunta estándar para algo que parece una tarea ... ¿qué has intentado? –

+2

Solo por cuestión de interés, ¿cómo es que estás usando una enumeración de trajes, pero no para el rango de la tarjeta también? – Kirschstein

Respuesta

14

Mezclar una baraja de cartas es algo que parece trivial al principio, pero por lo general el algoritmo que la mayoría de la gente presenta es incorrecto.

Jeff Atwood (Coding Horror) escribió unos muy buenos artículos sobre el tema:

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

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

(especialmente la segunda es una lectura obligada)

+0

Esto no es lo que estoy buscando. Estoy buscando a alguien que me muestre cómo barajar cartas a través del código que estoy usando –

+6

¿Está buscando a alguien que le escriba el código o le diga cómo hacerlo? (Suponiendo que se trata de una tarea, obtendrá más de la clase si la escribe usted mismo. Si no realiza la tarea, generalmente no aprueba la prueba.) – NoMoreZealots

41

Uso Fisher-Yates shuffle .

su código C# debe ser algo como esto:

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

FisherYates? Hmm, no sabía que había un nombre para eso. ¡La primera vez que implementé eso fue en un Atari de 8 bits en Basic! Creo que estaba en octavo grado. – NoMoreZealots

+0

obtengo estos errores cuando lo uso en mi clase Deck.cs En cada lugar dice Deck (sí, lo capitalicé para que coincida con mi código) dice que es un tipo 'pero se usa como una' variable '. y para cuando dice Deck.Length dice que Mi aplicación no tiene una definición para 'length' –

+1

No debe poner en mayúscula el nombre de la variable 'deck' para que coincida con su nombre de clase. Si lo haces, sí, obtendrás un error porque confundirás una variable con una clase. Otros te han dicho qué hacer: - crear un conjunto de 52 números enteros [0..51] incluido - barajan los enteros - repartir las cartas está removiendo el int superior de la matriz - tarjetas se representan como cadenas traduciendo valores enteros a la tarjeta + palo Buena suerte. – hughdbrown

5

Creo que este es un caso en el que sólo puede estar recibiendo demasiado atrapado en la abstracción.

Mezclar una baraja de cartas en el software es una cuestión de proporcionar la baraja al usuario en un orden aleatorio. En realidad, esto no requiere que barajes antes de tiempo.

Inicie su plataforma. (Me suelen utilizar un número de 1 a 52 para representar la tarjeta y mathmatically calcular qué tarjeta es.)

  1. Deal en la tarjeta mediante el uso de un generador de números aleatorios para recoger una tarjeta de la baraja de cartas availible.
  2. Cambia esa tarjeta con la del extremo del mazo.
  3. Disminuya un contador que apunta al extremo de la plataforma, para quitar esa tarjeta de la plataforma.
  4. Vaya al paso 1 hasta que termine de dibujar las tarjetas.

Editar: Y hablando en general, si usted tiene un buen número aleatorio generador no se gana nada "aleatorio" múltiples veces.

Esto debería ser posible utilizando las estructuras de datos que ha mostrado.Solo necesita agregar un método "Dibujar" y una variable miembro para realizar un seguimiento del final del mazo. Si estás empeñado en realizar el "shuffle" antes de tiempo, entonces A tu profesor es un idiota, B cada vez que saques 52 cartas, se barajará el mazo. Una vez que haya dibujado todas las cartas, debe proporcionar un método "DeckEmpty" y un método para restablecer End of Deck para incluir nuevamente todas las cartas.

-1

El barajado debe trabajar de esta manera:

se toman dos cartas al azar de la baraja (el índice de la carta de la baraja es los números aleatorios) Y intercambiará posiciones de las dos tarjetas. Por ejemplo, tome la tarjeta en el índice 2 y la tarjeta en el índice 9 y haga que cambien de lugar.

Y eso se puede repetir una cierta cantidad de veces.

El algoritmo debe ser algo como esto:

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

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

Esto no realiza una reproducción aleatoria. – dkarp

+0

¿Por qué no? Asumiendo funciones rnd.Next da valores totalmente aleatorios entre 1 y 52 – Rohit

+0

¿Cuánto tiempo tiene que mezclar para obtener 'suficientemente aleatorio'? –

2

el grupo aleatorio podría funcionar, pero no es muy eficiente y no realista. Usted debe tratar de esta manera:

//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 esta manera se puede obtener una reproducción aleatoria más realista con menos iteraciones

3

a barajar correcly una cubierta que NO debe utilizar sólo la clase Random, la semilla es sólo el 2^32 lo que significa que su objeto Random puede darle solo 2^32 (supuesto) orden diferente donde hay 52! (factorial 52) forma de agendar un mazo de la vida real.

estoy usando 2 GUID para crear 32bytes de datos aleatorios -> 8 semilla de 4bytes y barajar las cartas con ver estos 8 semillas diferentes

a continuación por medio de semillas que consigo un cierto número de tarjetas [5, 5,6,6,6,7,8,9]

aquí es el código que utilizo

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

¿Resolvería la clase criptográfica los issings del generador de números pseudoaleatorios? – ppumkin

+0

_ "su objeto Random puede darle solo 2^32 (supuesta) orden diferente" _ - en realidad, es "peor" que eso, porque una semilla negativa nunca se usa. Si uno pasa una semilla negativa al constructor, se usa el valor absoluto. Entonces "solo" tiene 2^31 secuencias posibles. Aún así, puse "peor" y "solo" entre comillas porque, para la mayoría de los propósitos, hay dos mil millones de secuencias posibles. –

-1

general, diría que vistazo a cada cubierta como un objeto que contiene una matriz de objetos de tarjeta , que cada objeto de la Tarjeta contiene un valor y una propiedad int suite, que se pueden aplicar d a un Enum de valores y suites para reunir la versión nombrada según el tipo de mazo que está utilizando. (Esto permitiría que este código sea más versátil y permita comparaciones de valores más fáciles 3 < 11 (jack)! ~) Su estilo funcionará para un proyecto escolar, ¡solo estoy obteniendo TOC con él!

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

Esto es suponiendo que utilizó una clase de cubierta base, entonces heredará, con el tipo de cubierta que desee (por lo que es por lo que se puede aplicar este mismo código para cubiertas Uno o lo que sea.) Código para el tipo normal, de la clase de la cubierta.

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

Hice un programa que contiene 7 cartas, luego baraja y espero tomarlas para ayudarlas.

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 

} 

}

Cuestiones relacionadas