【问题标题】:Null Reference Exception was Unhandled未处理空引用异常
【发布时间】:2013-12-25 08:33:43
【问题描述】:

这是一个非常简单的代码。我刚开始使用vb。我正在制作一个游戏,您可以将打乱的数字重新排序为正确的顺序。您尝试以最少的时间和最少的点击次数解决难题,并且下次玩游戏时,您会尝试获得较低的分数(或打破该记录)。您有 16 个按钮 (4x4) 和 15 个数字。有一个检查按钮功能可以查看是否解决了难题每次我调试程序时,它都会突出显示 Clicks 和 FinalTime 并说 Null Reference Exception was Unhandled。这是一些代码。

Public Class Form1
Dim Clicks As Integer = 0  'The variable that counts the number of times you clicked
Dim Time As Integer 'The vairable that holds the time
Dim TimeMin As Integer 'The variable that holds the minutes
Dim TimeSec As Integer  'The variable that holds the seconds
Dim FinalTime As String 'The variable that holds the final time (minutes and seconds)
Dim lngArray() As String = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", ""} {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", ""}    
Dim NumArray() As Integer
Dim NumArray1() As String

Private Sub CheckButton(ByRef Butt1 As Button, ByRef Butt2 As Button)
    If Butt2.Text = "" Then 'Checks if the button around the clicked number is empty "" It's the location of the empty square that you want the number in Butt1 to move to.
        Butt2.Text = Butt1.Text 'If it is, the value from Butt2 will "copy and paste" into Butt1
        Butt1.Text = "" 'Butt1 will keep the value and the value in Butt2 will clear "" 
        Clicks += 1 'Incrementing Each click by only 1. It's a counter. In addition, the code above only allows the click to increment by 1 if the number has moved. If you just click on a number that can't move, the click would not count.
    End If
    If Clicks > 1 Then
        lblTotal.Text = Clicks & " Clicks" 'Shows the total amount of clicks when it is greater than one
    Else
        lblTotal.Text = Clicks & " Click" 'Shows the total amount of clicks when it is one
    End If

End Sub

Private Sub CheckSolved() 'A private sub that checks if the puzzle is solved ,restarts the count, and stops the time
    Dim strName As String = "" 'The variable that has the string of the winners name
    If Me.Button1.Text = "1" And Me.Button2.Text = "2" And Me.Button3.Text = "3" And Me.Button4.Text = "4" And Me.Button5.Text = "5" And Me.Button6.Text = "6" And Me.Button7.Text = "7" And Me.Button8.Text = "8" And Me.Button9.Text = "9" And Me.Button10.Text = "10" And Me.Button11.Text = "11" And Me.Button12.Text = "12" And Me.Button13.Text = "13" And Me.Button14.Text = "14" And Me.Button15.Text = "15" Then 'Checks if the numbers are in the correct buttons
        Timer1.Enabled = False 'Stops the time
        strName = InputBox("What is your name", "Name of winner") 'Get's the winners name 
        MessageBox.Show("In " & FinalTime & " , you solved the puzzle in " & Me.Clicks & " clicks! Congratulations " & strName) 'Messagebox showing how many times you clicked to solve the puzzle. It gets the name you typed into the inputbox (strname) and displays it
        Call Restart() 'Shuffles the buttons and restarts the game when you win
        Call Record(NumArray, NumArray1)
    End If
End Sub
Private Sub Record(ByVal NumArray() As Integer, ByVal NumArray1() As String)
    'Make timemin array and then make time array. Then make click array
    For i As Integer = 0 To 1000 
        NumArray(i) = Clicks 'This is where the Null Reference error occured
        i = +1
        Array.Sort(NumArray) 'sorting the array values from least to greatest
    Next i

    lblRecordClicks.Text = NumArray(0) & " Clicks" 'displaying the lowest number of clicks in the label
    For k As Integer = 0 To 1000 'Making an  integer that captures 1000 values
        NumArray1(k) = FinalTime 'This is where the Null Reference error occured
        k = +1
        Array.Sort(NumArray1) 'sorting the array values from least to greatest
    Next k

    lblRecordTime.Text = NumArray1(0) 'displaying the lowest time in the label
End Sub

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
    Call Times()
End Sub

Private Sub Shuffle(ByVal lngArray As Object) 'Shuffles the values of the Array 
    Dim i As Long
    Dim iMin As Long
    Dim iMax As Long
    Dim lngReplace As Long
    Dim varSwap As Object
    iMin = LBound(lngArray)
    iMax = UBound(lngArray)
    For i = iMax To iMin + 1 Step -1
        lngReplace = Int((i - iMin + 1) * Rnd() + iMin)
        varSwap = lngArray(i)
        lngArray(i) = lngArray(lngReplace)
        lngArray(lngReplace) = varSwap
    Next
    Button1.Text = lngArray(0)
    Button2.Text = lngArray(1)
    Button3.Text = lngArray(2)
    Button4.Text = lngArray(3)
    Button5.Text = lngArray(4)
    Button6.Text = lngArray(5)
    Button7.Text = lngArray(6)
    Button8.Text = lngArray(7)
    Button9.Text = lngArray(8)
    Button10.Text = lngArray(9)
    Button11.Text = lngArray(10)
    Button12.Text = lngArray(11)
    Button13.Text = lngArray(12)
    Button14.Text = lngArray(13)
    Button15.Text = lngArray(14)
    Button16.Text = lngArray(15)
End Sub

Private Sub RestartToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RestartToolStripMenuItem.Click
    Call Restart()
    Call Me.btnStart_Click(sender, e) 'Call the button click to enable all buttons
End Sub
Private Sub Times()
    Time = Time + 1 'Increase the time by 1 second every interval
    TimeSec = TimeSec + 1 'Increase the time by 1 second every interval
    TimeMin = Convert.ToInt32(TimeSec \ 60) 'Takes the whole number of the amount of seconds divided by 60 and leaves out the remainder
    If Time >= 60 Then
        Time = 0
    End If
    'If the seconds pass 59 (and they do), it restarts to 0
    FinalTime = TimeMin & " min " & Time & " seconds" 'Final time is the string displayed showing the final time
    lblTime.Text = FinalTime 'The label displays the final time
End Sub
Private Sub Restart()
    Time = 0 'Resets the time
    Clicks = 0 'Resets the amount of clicks
    lblTotal.Text = "" 'Clears the label
    lblCheat.Visible = False
    lblTotal.Visible = True
    lblClicks.Visible = True
    lblQuote.Visible = True
    lblRecordClicks.Visible = True
    lblRecordTime.Visible = True
    'If the user cheated and hit the solve button and wants to restart and solve the puzzle on their own, then he can. Turning these label settings to true allows you to see them again
    Call Shuffle(lngArray) 'Shuffles the numbers
    Timer1.Enabled = True 'Continues the time when it resets to 0

End Sub

Public Sub RefreshEverythingToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RefreshEverythingToolStripMenuItem.Click
    Timer1.Enabled = False 'Pauses the timer
    If MessageBox.Show("Do you want to restart everything?", "Restart Game", MessageBoxButtons.YesNo, MessageBoxIcon.Information) = DialogResult.Yes Then
        Time = 0
        TimeSec = 0
        'Resets the time
        Clicks = 0 'Resets the amount of clicks
        lblTotal.Text = "" 'Clears the label
        lblRecordClicks.Text = "" 'Resets the record click
        lblRecordTime.Text = "" 'Resets the record time
    End If
    Call Shuffle(lngArray) 'Shuffles the numbers
    Timer1.Enabled = True 'Continues the timer if no is selected
    ReDim NumArray(1000) 'Clears the array data that was captured
    ReDim NumArray1(1000) 'Clears the array data that was captured
End Sub

End Class

如果您确实决定提供帮助(我希望您这样做),您是否可以尽量避免使用“计算机”谈话并尝试“为我提供帮助”。就像我之前说的,我对此很陌生。感谢您的宝贵时间。

【问题讨论】:

  • 异常发生在哪一行?
  • 在发生这种情况的行上有注释...'这是发生空引用错误的地方

标签: vb.net exception reference null


【解决方案1】:

您正在尝试将值保存到数组中。当你定义一个像Dim NumArray() As Integer 这样的数组时,没有为数组设置边界(数组基本上是Nothing),如果你尝试访问一个数组项,你会遇到空引用异常。 您只需在Public Sub RefreshEverythingToolStripMenuItem_Click 中设置数组边界。现在我不知道你的所有代码,但如果游戏在没有用户专门点击此按钮的情况下启动,那么你的数组将是 Nothing。 您必须确保始终在游戏开始之前设置数组边界。

您还可以在 .NET 中研究更抽象的类数组类型。例如,您可以尝试一个列表。 List 实际上是一个具有任意边界的数组。您可以使用 Of 关键字定义具有特定类型的列表,然后您可以使用列表的 Add 方法向其中添加项目、删除项目、对列表进行排序等。

定义为全局变量:

Dim FinalTimes as New List(Of Integer)
Dim FinalClicks as New List(Of Integer)

确保在此处使用 New 关键字。这意味着将创建一个 List 类的新对象。否则,您将再次在下面的行中遇到空引用异常。 当用户解决了这个难题后,您可以这样做:

FinalTimes.Add(FinalTime)
FinalClicks.Add(Clicks)
FinalTimes.Sort
FinalClicks.Sort

这基本上会将列表的长度增加一,将 FinalTime/Clicks 值写入最后一项,然后再使用两个列表。想法:对于高分,您可能希望将 FinalTime、Clicks 和 Player Name 连接到一个结构中,并使用 IComparer 接口让用户按名称/时间/Clicks 对高分列表进行排序。

  • 詹斯

PS:在我忘记之前:代码中发生异常的 For 循环没有真正意义。第一个问题是,在它们当前的形式中,它们将是无限循环,因为你总是在循环中将 i 设置为 1,而循环在 i=1000 时结束(显然这永远不会发生)。我想你的意思是i=i+1 或更短的i += 1。但它们仍然没有多大意义。我试过看看到底发生了什么(这并不明显:-))并且你的一半高分被新值覆盖等等。我认为上述方法会更容易。 :-)

【讨论】:

  • 如何在标签中显示已排序的 FinalTimes 和 FinalClicks?我不完全理解您对变量 FinalClicks 和 Final Times 排序的代码下方段落的解释。
  • FinalTimes.Sort 只会对列表中的值进行排序,不会显示它们。为了显示值,您可以创建自己的Function ListToString(ByVal l as List(Of Integer)) as String。在那里:Dim res as string = "",然后是For each i as integer in l,然后是res &= i.tostring,然后是Next,然后是Return resEnd Function。在您的代码中:lblTimes.Text = ListToString(FinalTimes)
猜你喜欢
  • 1970-01-01
  • 2013-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-29
  • 1970-01-01
  • 2014-06-06
相关资源
最近更新 更多