2009-07-19 3 views
13

Я пытаюсь написать код для проекта, в котором перечислены содержимое колоды карт, спрашивается, сколько раз человек хочет перетасовать колоду, а затем перетасовывает их. Он должен использовать метод для создания двух случайных целых чисел, используя класс System.Random.Карточка Shuffling in C#

Это мои классы:

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

Скажите, пожалуйста, как сделать карты перетасованными так, как хочет человек, а затем перечислить перетасованные карты.

+0

Исправлено форматирование для вас. –

+2

Стандартный вопрос для чего-то похожего на домашнюю работу ... что вы пробовали? –

+2

Просто из интереса, почему вы используете перечисление для костюмов, но не для ранга карты? – Kirschstein

ответ

14

Перемешивание колоды карт - это то, что сначала кажется тривиальным, но обычно алгоритм, который большинство людей придумывает, неверен.

Джефф Этвуд (Coding Horror) написал несколько очень хороших статей на эту тему:

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

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

(особенно второй один является обязательным читаемый)

+0

Это не то, что я ищу. Я ищу кого-то, чтобы показать мне, как перетасовывать карты через код, который я использую. – 2009-07-19 19:43:22

+6

Вы ищете кого-то, кто напишет вам код или расскажет, как это сделать? (Предполагая, что это задание, вы получите больше уроков из класса, если напишете его самостоятельно. Если вы не выполняете задание, вы обычно не выполняете тест.) – NoMoreZealots

41

Использование 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; 
     } 
    } 
} 
+1

FisherYates? Хм, я не знал, что это было имя. В первый раз я реализовал это на 8-битном Atari в Basic! Кажется, я был в 8-м классе. – NoMoreZealots

+0

Я получаю эти ошибки, когда я использую его в своем классе Deck.cs Каждое место, где говорится «Deck» (да, я использовал его в соответствии с моим кодом), он говорит, что это «тип», но используется как «переменная». и когда он говорит «Deck.Length», он говорит, что у моего приложения нет определения для «length» – 2009-07-20 05:28:00

+1

Вы не должны использовать значение переменной «deck» для имени вашего класса. Если да, вы получите ошибку, потому что вы будете путать переменную с классом. Другие говорили вам, что делать: - создать массив из 52 целых чисел [0..51] включительно - перетасовать целые - дело карты удаляет верхний Int из массива - карты представлены в виде строк путем перевода целочисленных значений в карту + костюм Удачи. – hughdbrown

5

Я думаю, что это тот случай, когда вы можете просто получать слишком схвачены в абстракции.

Перетасовка колоды карт в программное обеспечение - вопрос предоставления колоды пользователю в случайном порядке. Это фактически не требует, чтобы вы перетасовывали их раньше времени.

Инициируйте свою колоду. (Я обычно использую число от 1 до 52, чтобы представить карту и mathmatically вычислить какие карты.)

  1. Deal карты с помощью генератора случайных чисел, чтобы выбрать карту из колоды карт из Availible.
  2. Обмен этой карточкой с одной в конце колоды.
  3. Снимите счетчик, указывающий на конец колоды, чтобы извлечь эту карту из колоды.
  4. Перейти к шагу 1, пока вы не закончите рисование карт.

Edit: И вообще говоря, если у вас есть хороший генератор случайных чисел ничего не получил от «шаркая» это несколько раз.

Это должно быть возможно с использованием структур данных, которые вы указали.Вам просто нужно добавить метод «Draw» и переменную-член, чтобы отслеживать конец колоды. Если вы чертовски настроены на то, что на самом деле выполняете «перетасовку» раньше времени, тогда ваш твой профессор вздрагивает, B в любое время, когда вы нарисуете 52 карты, колода будет перетасована. После того, как вы нарисуете все карты, вам необходимо предоставить метод «DeckEmpty» и метод сброса End of Deck, чтобы снова включить все карты.

-1

перетасовка должна работать таким образом:

Берет две случайных карт в колоде (индексе карты в колоде есть случайные числа) И своп позиции два карт. Например, возьмите карту с индексом 2 и карточкой с индексом 9 и замените их на место.

И это может повторяться определенное количество раз.

Алгоритм должен выглядеть следующим образом:

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

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

Это не обеспечивает честную перетасовку. – dkarp

+0

Почему нет ??? Предполагая, что функции rnd.Next дают полностью случайные значения между 1 и 52 – Rohit

+0

Как долго вы должны перетасовывать, чтобы получить «достаточно случайный»? –

2

Ваш Перемешать может работать, но это не очень эффективно и не реалистичное. Вы должны попробовать этот способ:

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

Таким образом, вы можете получить более реалистичное перетасовать с меньшим количеством итераций

3

к correcly перетасовать колоду вы не должны только использовать случайный класс, семя только 2^32 что означает, что ваш случайный объект может дать вам только 2^32 (предположительно) другого порядка, где есть 52! (факториал 52) способ привязки реальной колоды жизни.

я использую 2 GUID создать 32 байт случайных данных -> 8 семя 4 байта и я перетасовать карты с thoses 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); 
      } 
     } 
    } 
+0

Может ли криптографический класс решить генератор псевдослучайных чисел? – ppumkin

+0

_ «Ваш случайный объект может дать вам только 2^32 (предположительно) другого порядка» _ - на самом деле это «хуже», чем потому, что отрицательное семя никогда не используется. Если вы передаете отрицательное семя конструктору, используется абсолютное значение. Таким образом, у вас «только» есть 2^31 возможных последовательностей. Тем не менее, я ставил «хуже» и «только» в кавычки, потому что для большинства целей 2 миллиарда возможных последовательностей много. –

-1

в целом, я бы сказал, что смотреть на каждой палубе в качестве объекта, который содержит массив объектов карты , каждый из которых содержит объект value и int int, который может быть использован d для перечисления значений и наборов для сбора именованной версии в соответствии с типом колоды, который вы используете. (Это позволит сделать этот бит кода более универсальным и упростить сравнение значений 3 < 11 (jack)! ~) Ваш стиль будет работать для школьного проекта, я просто получаю 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; 
     } 
    } 
} 

То есть предполагается, что вы использовали базовый класс Deck, то наследовать его типа колоды, которые вы хотите (что делает его таким образом Вы можете использовать этот же код для Uno палубах или что-либо.) Код для нормального типа класса колоды.

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

Я создал программу, содержащую 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 

} 

}