2009-07-19 68 views
13

Tôi đang cố gắng viết mã cho một dự án liệt kê các nội dung của một cỗ bài, hỏi người đó muốn xáo trộn bộ bài bao nhiêu lần rồi xáo trộn chúng. Nó phải sử dụng một phương thức để tạo ra hai số nguyên ngẫu nhiên bằng cách sử dụng lớp System.Random.Xáo trộn thẻ trong C#

Đây là lớp học của tôi:

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

Hãy cho tôi biết cách làm cho thẻ xáo trộn nhiều như người muốn và sau đó liệt kê các thẻ xáo trộn.

+0

Cố định định dạng cho bạn. –

+2

Câu hỏi tiêu chuẩn cho nội dung trông giống như bài tập về nhà ... bạn đã thử những gì? –

+2

Chỉ cần quan tâm, làm thế nào đến bạn đang sử dụng một enum cho phù hợp với nhưng không cho xếp hạng thẻ là tốt? – Kirschstein

Trả lời

14

Xáo trộn một cỗ bài có vẻ hơi tầm thường lúc đầu, nhưng thường là thuật toán mà hầu hết mọi người nghĩ ra là không chính xác.

Jeff Atwood (Coding Horror) đã viết một vài bài báo rất tốt về đề tài này:

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

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

(đặc biệt là điều thứ hai là một cuốn sách phải đọc)

+0

Đây không phải là những gì tôi đang tìm kiếm. Tôi đang tìm ai đó để chỉ cho tôi cách trộn thẻ thông qua mã tôi đang sử dụng –

+6

Bạn đang tìm ai đó để viết mã cho bạn hoặc cho bạn biết cách thực hiện? (Giả sử đây là một bài tập, bạn sẽ nhận được nhiều hơn từ các lớp học nếu bạn viết nó cho mình. Nếu bạn không làm nhiệm vụ bạn thường không kiểm tra.) – NoMoreZealots

41

Sử dụng Fisher-Yates shuffle .

Mã của bạn C# nên tìm một cái gì đó như thế này:

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

Ngư nghiệp? Hmm, tôi không biết có một cái tên cho nó. Lần đầu tiên tôi thực hiện được trên một Atari 8-bit trong cơ bản! Tôi nghĩ tôi học lớp 8. – NoMoreZealots

+0

tôi nhận được những lỗi này khi tôi sử dụng nó trong lớp Deck.cs Mỗi nơi nó nói Deck (vâng tôi đã viết hoa nó để khớp với mã của tôi) nó nói nó là một kiểu 'nhưng được sử dụng như một' biến '. và khi nó nói Deck.Length nó nói rằng ứng dụng của tôi không có định nghĩa cho 'length' –

+1

Bạn không nên viết hoa tên biến 'deck' để phù hợp với tên lớp của bạn. Nếu bạn làm, có, bạn sẽ nhận được một lỗi bởi vì bạn sẽ gây nhầm lẫn một biến với một lớp học. Những người khác đã cho bạn biết phải làm gì: - tạo một mảng gồm 52 số nguyên [0,.51] bao gồm - trộn các số nguyên - xử lý các thẻ đang xóa phần trên cùng khỏi mảng - thẻ được biểu diễn dưới dạng chuỗi bằng cách dịch các giá trị số nguyên sang thẻ + phù hợp với Chúc may mắn. – hughdbrown

5

Tôi nghĩ rằng đây là một trường hợp mà bạn có thể chỉ được nhận quá bắt kịp trong trừu tượng.

Xáo trộn một cỗ bài trong phần mềm là vấn đề cung cấp bộ bài cho người dùng theo thứ tự ngẫu nhiên. Điều này không thực sự yêu cầu bạn trộn chúng trước thời hạn.

Tắt sàn của bạn. (Tôi thường sử dụng một số từ 1 đến 52 để trình bày thẻ và tính toán loại thẻ nào là.)

  1. Giải quyết một thẻ bằng cách sử dụng trình tạo số ngẫu nhiên để chọn một thẻ ra khỏi thẻ khả dụng.
  2. Trao đổi thẻ đó với thẻ ở cuối boong.
  3. Giảm bộ đếm chỉ vào cuối bộ bài, để tháo thẻ đó khỏi boong.
  4. Goto bước 1 cho đến khi bạn vẽ xong.

Chỉnh sửa: Và nói chung, nếu bạn có trình tạo số ngẫu nhiên tốt, không có gì có được bằng cách "Xáo trộn" nhiều lần.

Điều này có thể thực hiện được bằng cách sử dụng cấu trúc dữ liệu bạn đã hiển thị.Bạn chỉ cần thêm phương thức "Vẽ" và biến thành viên để theo dõi kết thúc của bộ bài. Nếu bạn là địa ngục cong trên thực sự thực hiện "shuffle" trước thời hạn, sau đó A giáo sư của bạn là một jerk, B bất cứ lúc nào bạn rút ra 52 thẻ boong sẽ được xáo trộn. Khi bạn đã vẽ tất cả các thẻ, bạn cần cung cấp phương thức "DeckEmpty" và phương pháp để đặt lại End of Deck để bao gồm tất cả các thẻ một lần nữa.

-1

Các xáo trộn nên làm việc theo cách này:

Bạn lấy hai thẻ ngẫu nhiên trong boong (chỉ số của thẻ trong boong là những con số ngẫu nhiên) Và hoán đổi vị trí của hai thẻ. Ví dụ lấy thẻ tại chỉ số 2 và thẻ tại chỉ số 9 và yêu cầu họ thay đổi địa điểm.

Và điều đó có thể được lặp lại một số lần nhất định.

Thuật toán nên tìm một cái gì đó như thế này:

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

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

Điều này không thực hiện ngẫu nhiên công bằng. – dkarp

+0

Tại sao không ?? Giả sử các hàm rnd.Next cung cấp các giá trị hoàn toàn ngẫu nhiên giữa 1 và 52 – Rohit

+0

Bạn phải xáo trộn bao lâu để nhận được 'ngẫu nhiên đủ'? –

2

shuffle của bạn có thể làm việc, nhưng nó không thực sự hiệu quả và không thật. Bạn nên thử cách này:

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

Bằng cách này bạn có thể nhận được một shuffle thật hơn với sự lặp lại ít

3

để correcly xáo trộn một cỗ bạn không nên chỉ sử dụng lớp ngẫu nhiên, hạt giống duy nhất là 2^32 có nghĩa là đối tượng ngẫu nhiên của bạn có thể cung cấp cho bạn chỉ có 2^32 (nghĩa vụ) thứ tự khác nhau, nơi có 52! (giai thừa 52) cách thức làm một cuộc sống thực sự.

Tôi đang sử dụng 2 guid để tạo 32bytes dữ liệu ngẫu nhiên -> 8 hạt giống của 4bytes và tôi xáo trộn thẻ với 8 hạt giống khác nhau thoses

sau đó bằng hạt tôi nhận được một số lượng nhất định của thẻ [5, 5,6,6,6,7,8,9]

đây là đoạn code tôi sử dụng

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

Lớp mật mã sẽ giải mã các bộ tạo số giả ngẫu nhiên không? – ppumkin

+0

_ "đối tượng ngẫu nhiên của bạn có thể cung cấp cho bạn chỉ 2^32 (được cho là) ​​thứ tự khác nhau" _ - thực sự, nó "tệ hơn", bởi vì một hạt tiêu cực không bao giờ được sử dụng. Nếu người ta chuyển một hạt giống âm tới hàm khởi tạo, thì giá trị tuyệt đối được sử dụng. Vì vậy, bạn "chỉ" có 2^31 trình tự có thể. Tuy nhiên, tôi đặt "tồi tệ" và "chỉ" trong dấu ngoặc kép bởi vì, với hầu hết các mục đích, 2 tỷ chuỗi có thể là rất nhiều. –

-1

nói chung tôi muốn nói xem xét từng boong như một đối tượng, trong đó có một mảng của các đối tượng thẻ , mỗi đối tượng Thẻ chứa một giá trị và thuộc tính int của bộ, có thể là applie d cho một Enum các giá trị và dãy để thu thập phiên bản có tên theo Loại Deck bạn đang sử dụng. (Điều này sẽ cho phép bit mã này linh hoạt hơn và cho phép so sánh giá trị dễ dàng hơn 3 < 11 (jack)! ~) Phong cách của bạn sẽ hoạt động cho một dự án trường học, tôi chỉ nhận được OCD với nó!

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

Đó là giả định rằng bạn sử dụng một lớp cơ sở Deck, sau đó kế thừa nó vào loại boong mà bạn muốn (làm cho nó, do đó bạn có thể áp dụng cùng một mã này để sàn Uno hoặc những gì bao giờ hết.) Mã cho loại bình thường của tầng lớp.

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

Tôi đã tạo một chương trình chứa 7 thẻ, sau đó trộn và tôi hy vọng sẽ thực hiện để trợ giúp chúng.

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 

} 

}

Các vấn đề liên quan