2015-06-27 50 views
0

我试图模仿VB Express 2013中的“赛马”,这暴露了我对线程如何与Windows窗体一起工作的理解上的差距。这个想法是当按下表单上的一个按钮时,一个蓝色方块和一个红色方块(马)从左到右穿过一个表单(它有一个白色背景)。运动的每个增量应该是(伪)随机生成的,所以获胜者应该是不可预测的。在窗体上创建多个独立的线程

这是我用过的代码。广场的移动确实是随机的,但他们一起移动,而不是独立的,所以比赛总是一条平行线。如果我只在其中一个线程程序中包含随机化,它表现得更像是一场比赛,但胜者通常是可预测的。有人能告诉我我错过了什么吗?感谢预期。

Public Class Form1 

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 

     Dim t1 As System.Threading.Thread 
     Dim t2 As System.Threading.Thread 

     t1 = New System.Threading.Thread(AddressOf RedHorse) 
     t2 = New System.Threading.Thread(AddressOf BlueHorse) 

     t1.Start() 
     t2.Start() 

    End Sub 

    Public Sub RedHorse() 
     Randomize() 
     Dim G As Graphics 
     G = Me.CreateGraphics 
     Dim bRed As Brush 
     bRed = New SolidBrush(Color.Red) 
     Dim bWhite As Brush 
     bWhite = New SolidBrush(Color.White) 

     Dim x1 As Integer 
     x1 = 100 

     G.FillRectangle(bWhite, x1, 100, 50, 50) 

     Do Until x1 >= 800 
      x1 = x1 + Rnd() 
      G.FillRectangle(bRed, x1, 100, 50, 50) 
      Threading.Thread.Sleep(1) 
      G.FillRectangle(bWhite, x1, 100, 50, 50) 
     Loop 
    End Sub 

    Public Sub BlueHorse() 
     Randomize() 
     Dim G As Graphics 
     G = Me.CreateGraphics 
     Dim bBlue As Brush 
     bBlue = New SolidBrush(Color.Blue) 
     Dim bWhite As Brush 
     bWhite = New SolidBrush(Color.White) 

     Dim x2 As Integer 
     x2 = 100 

     G.FillRectangle(bWhite, x2, 200, 50, 50) 

     Do Until x2 >= 800 
      x2 = x2 + Rnd() 
      G.FillRectangle(bBlue, x2, 200, 50, 50) 
      Threading.Thread.Sleep(1) 
      G.FillRectangle(bWhite, x2, 200, 50, 50) 
     Loop 

    End Sub 

    Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown 

     Dim G As Graphics 
     G = Me.CreateGraphics 
     Dim bRed As Brush 
     bRed = New SolidBrush(Color.Red) 
     Dim bBlue As Brush 
     bBlue = New SolidBrush(Color.Blue) 

     G.FillRectangle(bRed, 100, 100, 50, 50) 
     G.FillRectangle(bBlue, 100, 200, 50, 50) 

    End Sub 
End Class 
+0

除了Randomize问题,我不认为你可以从线程更新图形。在线程中进行位置计算并使用计时器以计算位置更新HMI。 – Graffito

回答

0

首先不要使用随机化,使用随机类,阅读这个。基本问题是线程同时启动,然后在两个循环之间休眠同一时间。这是您的代码,只需进行一些更改。

Public Class Form1 

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 

     'Me.Width = 1000 'testing 
     isWinner = -1 

     Dim t1 As System.Threading.Thread 
     Dim t2 As System.Threading.Thread 

     t1 = New System.Threading.Thread(AddressOf RedHorse) 
     t2 = New System.Threading.Thread(AddressOf BlueHorse) 

     t1.Start() 
     t2.Start() 

    End Sub 

    Dim prng As New Random 
    Const maxMove As Integer = 21 
    Const maxSleep As Integer = 51 
    Dim isWinner As Integer = -1 

    Public Sub RedHorse() 
     Threading.Thread.Sleep(prng.Next(maxSleep)) 
     Dim G As Graphics 
     G = Me.CreateGraphics 
     Dim bRed As Brush 
     bRed = New SolidBrush(Color.Red) 
     Dim bWhite As Brush 
     bWhite = New SolidBrush(Color.White) 

     Dim x1 As Integer 
     x1 = 100 

     G.FillRectangle(bWhite, x1, 100, 50, 50) 

     Do While x1 < 800 AndAlso isWinner < 0 
      x1 = x1 + prng.Next(maxMove) 
      G.FillRectangle(bRed, x1, 100, 50, 50) 
      Threading.Thread.Sleep(prng.Next(maxSleep)) 
      G.FillRectangle(bWhite, x1, 100, 50, 50) 
     Loop 
     'G.FillRectangle(bRed, x1, 100, 50, 50) 
     If isWinner < 0 Then 
      isWinner = 1 
     End If 
    End Sub 

    Public Sub BlueHorse() 
     Threading.Thread.Sleep(prng.Next(maxSleep)) 
     Dim G As Graphics 
     G = Me.CreateGraphics 
     Dim bBlue As Brush 
     bBlue = New SolidBrush(Color.Blue) 
     Dim bWhite As Brush 
     bWhite = New SolidBrush(Color.White) 

     Dim x2 As Integer 
     x2 = 100 

     G.FillRectangle(bWhite, x2, 200, 50, 50) 

     Do While x2 < 800 AndAlso isWinner < 0 
      x2 = x2 + prng.Next(maxMove) 
      G.FillRectangle(bBlue, x2, 200, 50, 50) 
      Threading.Thread.Sleep(prng.Next(maxSleep)) 
      G.FillRectangle(bWhite, x2, 200, 50, 50) 
     Loop 
     'G.FillRectangle(bBlue, x2, 200, 50, 50) 
     If isWinner < 0 Then 
      isWinner = 2 
     End If 
    End Sub 

    Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown 

     Dim G As Graphics 
     G = Me.CreateGraphics 
     Dim bRed As Brush 
     bRed = New SolidBrush(Color.Red) 
     Dim bBlue As Brush 
     bBlue = New SolidBrush(Color.Blue) 

     G.FillRectangle(bRed, 100, 100, 50, 50) 
     G.FillRectangle(bBlue, 100, 200, 50, 50) 
    End Sub 
End Class 
+0

感谢dbasnett为您改进的代码 - 它完成了我想要的工作。我发现,在Random类中,您事先已经生成了一组随机数。从这个意义上说,每场比赛的结果都是预先规定的(但我想这是无论如何)。我仍然无法理解为什么我最初的尝试不起作用;每个'马'产生一个随机数来控制下一步的移动。我推测这对每匹马来说都是不同的,因为rnd被用在不同的线程上?不过谢谢。 – Drummy