2011-11-13 21 views
3

我有一個標準的52張牌組成的陣列。每張卡片都被表示爲一個整數。我寫了下面的函數來洗牌。下面的代碼看起來好嗎?寫一個方法在VB.NET中洗牌一套

Module Module3 

Sub Main() 

    ' initialize array 
    Dim Cards(52) As Integer 

    ' Unit Test 
    ' Pass array as argument. 
    Console.WriteLine(shuffle(Cards)) 

End Sub 

Function shuffle(ByVal Cards() As Integer) 

    Dim counter = 1 
    Dim rand = New Random() 

    For Each card In Cards 

     ' Grab random number with range of 52 
     Dim n = rand.Next(52) 

     ' Pick a card 
     Dim temp = Cards(counter) 

     ' Swap picked card with random card 
     Cards(counter) = Cards(n) 
     Cards(n) = temp 

     counter += 1 

    Next 

    Return (Cards) 

End Function 

End Module 
+0

可能重複/ 554587/is-there-an-easy-way-to-randomize-a-list-in-vb-net) –

+0

@Bruno - 考慮使用列表。請參閱我提供的代碼。 – dbasnett

回答

4

不,代碼不會做你說的。

Dim Cards(52) As Integer 

這將建立一個數組爲53卡,不52.:

Dim Cards(51) As Integer 

洗牌時,交換各卡在甲板早卡(或本身),而不是在任何地方在甲板。 (這是Fisher-Yates shuffle的原理。)

而不是從循環中分離一個計數器,使用計數器循環。

Dim rand = New Random() 

For counter = 0 to Cards.Length - 1 

    Dim n = rand.Next(counter + 1) 

    Dim temp = Cards(counter) 
    Cards(counter) = Cards(n) 
    Cards(n) = temp 

Next 
1

如果這將被用於一些遊戲,我不會用數組,我會使用,因爲容易項目的列表可以添加/刪除。

Module Module1 

    Dim deck As New List(Of Integer) 
    Dim prng As New Random 

    Sub Main() 
     newDeck() 
     showDeck() 
     shuffle() 
     showDeck() 
     Dim s As String 
     Do 
      s = Console.ReadLine() 
      Select Case s 
       Case "s" 
        showDeck() 
       Case "c" 
        If deck.Count = 0 Then 
         Console.WriteLine("No cards") 
        Else 
         'take top card 
         Dim foo As Integer = deck(0) 
         deck.RemoveAt(0) 
         Console.WriteLine(foo.ToString) 
        End If 
       Case "n" 
        newDeck() 
        shuffle() 
      End Select 
     Loop Until s.ToLower = "x" 
    End Sub 

    Sub newDeck() 
     deck = Enumerable.Range(1, 52).ToList 'create deck 
    End Sub 

    Sub shuffle() 
     deck = deck.OrderBy(Function(r) prng.Next).ToList 
    End Sub 

    Sub showDeck() 
     Dim ctr As Integer = 0 
     Console.WriteLine() 
     For Each card As Integer In deck 
      Console.Write("{0}", card.ToString.PadLeft(4, " "c)) 
      ctr += 1 
      If ctr Mod 10 = 0 Then Console.WriteLine() 
     Next 
     Console.WriteLine() 
    End Sub 
End Module 

一段時間以來,我一直認爲這是一個計算機不應該完全模仿現實世界的情況。首先,這是一個程序,用於瞭解隨機數生成器的種子的問題。

'create a form with three buttons and a richtextbox 
Dim deckIdx As New List(Of Integer) 
Dim cards As New List(Of card) 
Dim prng As New Random 

Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click 
    newDeck() 
    shuffle() 
    showDeck() 
End Sub 

Private Sub Button3_Click(sender As System.Object, e As System.EventArgs) Handles Button3.Click 
    'show next five cards 
    Dim sb As New System.Text.StringBuilder 
    sb.AppendLine() 
    For x As Integer = 1 To 5 
     Dim foo As card = getTopCard() 
     If Not foo Is Nothing Then sb.AppendFormat("{0}", foo.theCard.ToString.PadLeft(4, " "c)) 
    Next 
    RichTextBox1.AppendText(sb.ToString) 
    RichTextBox1.ScrollToCaret() 
End Sub 

Private Sub Form1_Shown(sender As Object, e As System.EventArgs) Handles Me.Shown 
    Button1.PerformClick() 
End Sub 

Class card 
    Public theCard As Integer 
    Public count As Integer 
End Class 

Sub newDeck() 
    prng = New Random(42) '<<<<<<<<<<<<<<<<<<<<<<<< OOPS!!! 
    deckIdx = Enumerable.Range(0, 51).ToList 'create deck indicies 
    cards = New List(Of card) 
    For Each cIDX As Integer In deckIdx 
     Dim foo As New card 
     foo.theCard = cIDX 
     foo.count = 0 
     cards.Add(foo) 
    Next 
End Sub 

Sub shuffle() 
    deckIdx = deckIdx.OrderBy(Function(r) prng.Next).ToList 
End Sub 

Function getTopCard() As card 
    If deckIdx.Count > 0 Then 
     Dim foo As New card 
     foo.theCard = cards(deckIdx(0)).theCard 
     foo.count = cards(deckIdx(0)).count 
     deckIdx.RemoveAt(0) 
     Return foo 
    Else 
     Return Nothing 
    End If 
End Function 

Sub showDeck() 
    Dim ctr As Integer = 0 
    Dim sb As New System.Text.StringBuilder 
    For Each card As Integer In deckIdx 
     sb.AppendFormat("{0}", cards(card).theCard.ToString.PadLeft(4, " "c)) 
     ctr += 1 
     If ctr Mod 10 = 0 Then sb.AppendLine() 
    Next 
    RichTextBox1.Text = sb.ToString 
End Sub 

運行該程序並重覆按下按鈕1/3將產生相同的結果,一遍又一遍。如果我們要堅持計算機必須完全模仿現實世界的想法,那麼顯而易見的解決方案是不重新實現PRNG。但是,如果我們採取了不同的方法。

像以前一樣添加該代碼

Dim bkgShuffle As Threading.Thread 
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click 
    Button2.Enabled = False 
    bkgShuffle = New Threading.Thread(AddressOf shuffleBkg) 
    bkgShuffle.IsBackground = True 
    bkgShuffle.Start() 
End Sub 

Sub shuffleBkg() 
    Do 
     Threading.Thread.Sleep(50) 
     shuffle() 
    Loop 
End Sub 

運行程序,按下按鈕1和3以確認一切都沒有改變。當您滿意時按下按鈕2,然後按下按鈕1和3.

當您親自玩牌時,顯然該牌不會不斷被洗牌,但如果它是?它會改變什麼嗎?如果我在線上玩牌,我是否知道或關心牌組是否在不斷洗牌?

這段代碼只是爲了證明一個觀點,在盒子外思考,而不應該被認爲是成品。

編輯: Bull Mountain可能會影響這一些。

+0

非常好。謝謝! – Bruno

+0

什麼會終止您的shuffleBkg方法中的無限循環? –

+0

應用程序結束。正如我所說,這是爲了表明一點。 – dbasnett

0

這是現在正式稱爲「布里格斯」洗牌

Module module1 

Dim cards(51) As String 
Dim trues(51) As Boolean 
Dim number, Truecheck As Integer 
Dim stores, loopy As String 

Sub main() 

    number = 1 

    cards(0) = "Ace of Spades" 
    cards(10) = "Jack of Spades" 
    cards(11) = "Queen of Spades" 
    cards(12) = "King of Spades" 

    cards(13) = "Ace of Clubs" 
    cards(23) = "Jack of Clubs" 
    cards(24) = "Queen of Clubs" 
    cards(25) = "King of Clubs" 

    cards(26) = "Aec of Diamonds" 
    cards(36) = "Jack of Diamods" 
    cards(37) = "Queen of Diamonds" 
    cards(38) = "King of Diamonds" 

    cards(39) = "Ace of Hearts" 
    cards(49) = "Jack of Heats" 
    cards(50) = "Queen of Hearts" 
    cards(51) = "King of Hearts" 


    For i = 1 To 9 
     number = number + 1 
     cards(i) = number.ToString + " of Spades" 
    Next 

    number = 1 

    For i = 14 To 22 
     number = number + 1 
     cards(i) = number.ToString + " of Clubs" 
    Next 

    number = 1 

    For i = 27 To 35 
     number = number + 1 
     cards(i) = number.ToString + " of Diamonds" 
    Next 

    number = 1 

    For i = 40 To 48 
     number = number + 1 
     cards(i) = number.ToString + " of Hearts" 
    Next 

    For i = 0 To 51 
     Console.WriteLine(cards(i)) 
    Next 


    Console.WriteLine("") 
    Console.WriteLine("") 

    For i = 0 To 51 

linetrue: 

     Randomize() 
     stores = cards(i) 
     Truecheck = Int(Rnd() * 51) 
     If trues(Truecheck) = True Then GoTo linetrue 

     trues(i) = True 
     cards(i) = cards(Truecheck) 
     cards(Truecheck) = stores 
     Console.WriteLine(cards(i)) 

    Next 


End Sub 


End Module 
的[有沒有一種簡單的方法隨機在VB.NET?](http://stackoverflow.com/questions列表