VB.Net绘制二叉树

时间:2017-02-14 10:34:29

标签: vb.net graphics tree binary-tree nodes

本质上,该程序的目的是进行修订。该程序将生成一个随机数学表达式,将其转换为二叉树的可视化表示,用户必须遍历二叉树。但是,当我运行此代码时,初始节点远离中心。我如何重新定位二进制树位于PictureBox的中间?这是我的代码: 公共班级BTT     '已宣布的可变性不是故障     昏暗节点(7)作为对象

'maybe try to alter the form so that the user can only get two incorrect answers' 
Dim operators(6) As String
Dim actualAnswer As String = ""
Dim ogEquation(11) As String
Dim newLabel As String = "" 'used to store the equation to be stored in the label' 
Dim userAnswer As String
Dim myTime As Double

Dim traversal(3) As String
Dim selectedTraversal As String
Dim treeCounter As Integer = 0
Dim draw As Boolean = False

Structure tree
    Dim name As String
    Dim left As Integer
    Dim right As Integer
End Structure
Dim TreeNode(7) As tree

Dim scoreValue As Integer = 0 'stores the user's score for the game just completed'  
Dim updating As Boolean = False 'if there are already 10 scores, the first one will need to be removed, so updating = true' 
Class node
    Public lineColour As Color
    Public lineWidth As Integer
    Public posX As Integer
    Public posY As Integer
    Public radius As Integer

    Public Sub draw(e As PaintEventArgs)
        Dim myPen As New Pen(Me.lineColour, Me.lineWidth)
        e.Graphics.DrawEllipse(myPen, Me.posX, Me.posY, Me.radius, Me.radius)
    End Sub
End Class

Sub DrawTree()
    'these are the coordinates of the top left of the PictureBox 
    Dim leftX As Integer = 171
    Dim rightX As Integer = 171 + PictureBox1.Width 'will be set to the edge of the picturebox 
    Dim topY As Integer = 138
    Dim bottomY As Integer = 138 + PictureBox1.Height 'will be that number of pixels down, WILL NEVER CHANGE
    Dim currentNode As Integer = 1 'will initially be the root node
    For i = 1 To treeCounter 'loops based on the number of nodes in the array'
        'assigns the basic information common to all of the nodes 
        nodes(i) = New node
        nodes(i).radius = 70
        nodes(i).lineWidth = 2
        nodes(i).lineColour = Color.Black
    Next
    'need to go through the binary tree and determine x & y positions, with labels inside the ellipses
    ConstructTree(currentNode, leftX, rightX, topY, bottomY)
    draw = True
    PictureBox1.Refresh()
End Sub

Sub ConstructTree(ByRef currentNode As Integer, ByRef leftX As Integer, ByRef rightX As Integer, ByRef topY As Integer, ByRef bottomY As Integer)
    'ASK ISABEL ABOUT DYNAMICALLY GENERATING A LABEL'
    'e.g. Dim test As New Label
    nodes(currentNode).posX = (leftX + rightX) / 2 'gets average of x coordinates'
    nodes(currentNode).posY = topY + ((bottomY - topY) * (1 / 3)) 'gets number of pixels down between bottom of form & last node, goes a third of the way down
    If TreeNode(currentNode).left <> 0 Then 'if there is a node to the left 
        ConstructTree(TreeNode(currentNode).left, leftX, (leftX + rightX) / 2, nodes(currentNode).posY, bottomY)
    End If

    If TreeNode(currentNode).right <> 0 Then 'if there is a node to the right
        ConstructTree(TreeNode(currentNode).right, (leftX + rightX) / 2, rightX, nodes(currentNode).posY, bottomY) 'swaps the left and right x-coords which have been changed
    End If
End Sub

Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
    If draw = True Then
        For i = 1 To treeCounter
            nodes(i).draw(e)
        Next
        'ALSO need to draw lines between the nodes, but IGNORE FOR NOW
    End If
End Sub

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
    TextBox1.Text = myTime - (0.1)
    myTime = TextBox1.Text

    If myTime = 0 Then
        Timer1.Enabled = False
        MsgBox("Time is up!")
        checkupdate()
        resetForm()
    End If
    'add another if statement checking for two wrong answers, will stop the timer and tell the user that they have got too man questions wrong' 
End Sub

Sub resetForm()
    Score.Text = "Score:"
    Label1.Text = ""
    scoreValue = 0
End Sub

Sub writefile()
    FileOpen(1, "BTTscores.txt", OpenMode.Output)
    Select Case updating
        Case True
            For i = 2 To 11
                WriteLine(1, scores(i))
            Next
        Case False
            For i = 1 To numberOfScores + 1
                WriteLine(1, scores(i))
            Next
    End Select
    FileClose()
End Sub

Sub checkupdate()
    'need to check whether there are already ten elements in the array. If so, then delete the first score, move all the indices of the other scores 1 to the left and add the new scores on the end'
    numberOfScores = 0 'will need to be reset if the user carries on using the program' 
    FileOpen(1, "BTTscores.txt", OpenMode.Input) 'need to bubble sort values' 
    Dim line As String
    Do Until EOF(1)
        line = LineInput(1)
        If line <> "" Then
            numberOfScores = numberOfScores + 1
            scores(numberOfScores) = line 'copies the line to the array' 
        End If
    Loop

    If numberOfScores = 10 Then 'if one needs to be updated, need to read all but the first line into the array' 
        updating = True
        scores(11) = scoreValue
    Else 'if there are less than 10 scores, the user's current score just needs to be added on the end'
        updating = False
        scores(numberOfScores + 1) = scoreValue
    End If
    FileClose(1)
    writefile()
End Sub

Private Sub EnterButton_Click(sender As Object, e As EventArgs) Handles EnterButton.Click
    userAnswer = Answer.Text
    If actualAnswer.Replace(" ", "") = userAnswer.Replace(" ", "") Then
        UpdateScore()
    End If
    Score.Text = ("Score: " & scoreValue)
    Answer.Text = ""
    InitialSetup()
End Sub

Sub UpdateScore()
    Select Case difficulty
        Case "Easy"
            scoreValue = scoreValue + 10
        Case "Medium"
            scoreValue = scoreValue + 15
        Case "Hard"
            scoreValue = scoreValue + 20
    End Select
End Sub

Private Sub StartButton_Click(sender As Object, e As EventArgs) Handles StartButton.Click
    scoreValue = 0
    Initialisation()
    InitialSetup()
    myTime = 60
    Timer1.Enabled = True
End Sub

Sub InitialSetup()
    Dim currentNode As Integer = 1 'will be root node' 
    actualAnswer = ""
    GetEquation()
    newLabel = ""
    selectedTraversal = traversal(CInt(Math.Floor((3 - 1 + 1) * Rnd())) + 1) 'will choose a random traversal' 
    newLabel = "Traversal: " + selectedTraversal
    Label1.Text = newLabel
    If selectedTraversal = "Prefix" Then
        PrefixConversion(currentNode)
    ElseIf selectedTraversal = "Infix" Then
        InfixConversion()
    Else
        RPConversion()
    End If
    DrawTree()

End Sub

Sub Initialisation()
    operators(1) = "("
    operators(2) = "-"
    operators(3) = "+"
    operators(4) = "*"
    operators(5) = "/"
    operators(6) = ")"

    traversal(1) = "Prefix"
    traversal(2) = "Infix"
    traversal(3) = "Postfix"
End Sub

Sub GetEquation()
    Select Case difficulty
        'RANDOM NUMBER FORMAT: CInt(Math.Floor((upperbound - lowerbound + 1) * Rnd())) + lowerbound'   
        Case "Easy"
            'FORMAT: 17 * 4'   
            treeCounter = 3
            ogEquation(1) = CInt(Math.Floor((20 - 1 + 1) * Rnd())) + 1
            ogEquation(2) = operators(CInt(Math.Floor((5 - 2 + 1) * Rnd())) + 2)
            ogEquation(3) = CInt(Math.Floor((20 - 1 + 1) * Rnd())) + 1

            'initialising the binary tree iteration'
            TreeNode(1).name = ogEquation(2) 'operator is the root' 
            TreeNode(1).left = 2
            TreeNode(1).right = 3

            TreeNode(2).name = ogEquation(1)
            TreeNode(3).name = ogEquation(3)
            'EG: * 17 4 
        Case "Medium"
            treeCounter = 5
            'FORMAT: 15 * (17 + 4)'   
            ogEquation(1) = CInt(Math.Floor((50 - 1 + 1) * Rnd())) + 1
            ogEquation(2) = operators(CInt(Math.Floor((5 - 2 + 1) * Rnd())) + 2)
            ogEquation(3) = operators(1)
            ogEquation(4) = CInt(Math.Floor((50 - 1 + 1) * Rnd())) + 1
            ogEquation(5) = operators(CInt(Math.Floor((5 - 2 + 1) * Rnd())) + 2)
            ogEquation(6) = CInt(Math.Floor((50 - 1 + 1) * Rnd())) + 1
            ogEquation(7) = operators(6)


            'initialising the binary tree iteration'
            TreeNode(1).name = ogEquation(2) 'root node' 
            TreeNode(1).left = 2
            TreeNode(1).right = 3

            TreeNode(2).name = ogEquation(1)

            TreeNode(3).name = ogEquation(5)
            TreeNode(3).left = 4
            TreeNode(3).right = 5

            TreeNode(4).name = ogEquation(4)
            TreeNode(5).name = ogEquation(6)
            'EG: * 15 + 17 4 

        Case "Hard"
            'FORMAT: (17 + 4) * (20 / 10), random numbers are 1-150'   
            treeCounter = 7
            ogEquation(1) = operators(1)
            ogEquation(2) = CInt(Math.Floor((150 - 1 + 1) * Rnd())) + 1
            ogEquation(3) = operators(CInt(Math.Floor((5 - 2 + 1) * Rnd())) + 2)
            ogEquation(4) = CInt(Math.Floor((150 - 1 + 1) * Rnd())) + 1
            ogEquation(5) = operators(6)
            ogEquation(6) = operators(CInt(Math.Floor((5 - 2 + 1) * Rnd())) + 2)
            ogEquation(7) = operators(1)
            ogEquation(8) = CInt(Math.Floor((150 - 1 + 1) * Rnd())) + 1
            ogEquation(9) = operators(CInt(Math.Floor((5 - 2 + 1) * Rnd())) + 2)
            ogEquation(10) = CInt(Math.Floor((150 - 1 + 1) * Rnd())) + 1
            ogEquation(11) = operators(6)


            'initialising the binary tree iteration'
            TreeNode(1).name = ogEquation(6) 'root node' 
            TreeNode(1).left = 2
            TreeNode(1).right = 5

            TreeNode(2).name = ogEquation(3)
            TreeNode(2).left = 3
            TreeNode(2).right = 4

            TreeNode(3).name = ogEquation(2)
            TreeNode(4).name = ogEquation(4)

            TreeNode(5).name = ogEquation(9)
            TreeNode(5).left = 6
            TreeNode(5).right = 7

            TreeNode(6).name = ogEquation(8)
            TreeNode(7).name = ogEquation(10)
            'EG: * + 17 4 / 20 10
    End Select
End Sub

'Traversal Solutions'  

'Postfix Conversion'  
Sub RPConversion()
    Dim myStack As New Stack(15)
    Dim empty As Boolean = True
    Dim temp As String 'used to store the current part of the original equation'   
    Dim operatorNum As Integer
    Dim peekNum As Integer
    Dim stoploop As Boolean = True
    For i = 1 To ogEquation.Count - 1 'will iterate through the total number of elements in the array ogEquation'   
        If myStack.Count = 0 Then empty = True
        temp = ogEquation(i)
        MatchTempOperation(myStack, temp, operatorNum)

        If operatorNum > 1 And operatorNum < 6 Then 'if the value is an operator'   
            If myStack.Count <> 0 Then 'if the stack contains a value'  
                CheckPeek(myStack, peekNum)
                If operatorNum > peekNum Then
                    myStack.Push(temp)
                ElseIf operatorNum = peekNum Then
                    actualAnswer = actualAnswer + myStack.Pop()
                    myStack.Push(temp)
                Else 'operatorNum < peekNum'   

                    actualAnswer = actualAnswer + myStack.Pop()
                    Do
                        stoploop = True
                        CheckPeek(myStack, peekNum)
                        If operatorNum > peekNum Then
                            myStack.Push(temp)
                        ElseIf operatorNum = peekNum Then
                            actualAnswer = actualAnswer + myStack.Pop()
                            myStack.Push(temp)
                        Else
                            actualAnswer = actualAnswer + myStack.Pop()
                            stoploop = False
                        End If
                    Loop Until stoploop Or myStack.Count = 0
                End If
            Else
                myStack.Push(temp)
            End If

        ElseIf temp = "(" Then
            myStack.Push(temp)
        ElseIf temp = ")" Then
            Do
                actualAnswer = actualAnswer + myStack.Pop()
            Loop Until myStack.Peek() = "("
            myStack.Pop()
        Else
            actualAnswer = actualAnswer + temp
        End If
        operatorNum = 0
    Next

    If myStack.Count > 0 Then
        For i = 1 To myStack.Count
            actualAnswer = actualAnswer + myStack.Pop()
        Next
    End If
End Sub

Sub CheckPeek(ByVal myStack As Stack, ByRef peekNum As Integer) 'does the same as MatchTempOperation but for the top of the stack'   
    For i = 2 To 5 'skip one and six because we know it isn't a left or right bracket'   
        If myStack.Peek() = operators(i) Then
            peekNum = i
        End If
    Next
End Sub

Sub MatchTempOperation(ByVal myStack As Stack, ByVal temp As String, ByRef operatorNum As Integer) 'wants to look at the stack but not be able to change it'   
    For i = 1 To 6
        If temp = operators(i) Then
            operatorNum = i
        End If
    Next
End Sub

'Infix'  
Sub InfixConversion()
    For i = 1 To 11
        'check each element for empty spaces / brackets' 
        If ogEquation(i) <> "" And ogEquation(i) <> "(" And ogEquation(i) <> ")" Then
            actualAnswer = actualAnswer + ogEquation(i)
        End If
    Next
End Sub

'Prefix' 
Sub PrefixConversion(ByRef currentNode As Integer)
    actualAnswer = actualAnswer + TreeNode(currentNode).name
    If TreeNode(currentNode).left <> 0 Then
        PrefixConversion(TreeNode(currentNode).left)
    End If

    If TreeNode(currentNode).right <> 0 Then
        PrefixConversion(TreeNode(currentNode).right)
    End If
End Sub

Private Sub ExitButton_Click(sender As Object, e As EventArgs) Handles ExitButton.Click
    Me.Hide()
End Sub

结束班

对于效率低下的道歉,请注意“难度”变量是公共的并存储在此表单之外。谢谢:)

输出: enter image description here 如您所见,根节点远离左下方的中心。

0 个答案:

没有答案