0xSingularity
0xSingularity

Reputation: 570

Iterating through the elements in each row of a 2d array (vb.net)

Ok let me explain my question, here I have a 4x4 array of picture boxes which looks like this:

       C1 C2 C3 C4 
Row 1: [] [] [] []
Row 2: [] [] [] []
Row 3: [] [] [] []
Row 4: [] [] [] []

When the user presses on one of the picture boxes the background color of the picture box changes. I am trying to iterate through each of the rows to figure out which pictures box's have a red background per row. The timer interval is set in Beats Per Minute (60000 / textbox1.text). How do I accomplish this? I made the 2d array but the iteration is not working.

    Dim graph(4, 4) As PictureBox

    graph(1, 1) = PictureBox1
    graph(1, 2) = PictureBox2
    graph(1, 3) = PictureBox3
    graph(1, 4) = PictureBox4
    graph(2, 1) = PictureBox5
    graph(2, 2) = PictureBox6
    graph(2, 3) = PictureBox7
    graph(2, 4) = PictureBox8
    graph(3, 1) = PictureBox9
    graph(3, 2) = PictureBox10
    graph(3, 3) = PictureBox11
    graph(3, 4) = PictureBox12
    graph(4, 1) = PictureBox13
    graph(4, 2) = PictureBox14
    graph(4, 3) = PictureBox15
    graph(4, 4) = PictureBox16

Private Sub Button5_Click_1(sender As System.Object, e As System.EventArgs) Handles Button5.Click
    Dim tempo As Integer = CInt(TextBox1.Text)
    Dim BPM As Integer = 60000 / tempo
    Timer1.Interval = BPM
    Timer1.Enabled = True
End Sub

Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
    For i As Integer = 1 To 4

        Select Case i
            Case 1
                For value As Integer = 1 To 4
                    If graph(1, value).BackColor = Color.Red Then
                        MsgBox("sfd")
                    End If
                Next
            Case 2
                For value As Integer = 1 To 4
                    If graph(2, value).BackColor = Color.Red Then
                        MsgBox("sfd")
                    End If
                Next
            Case 3
                For value As Integer = 1 To 4
                    If graph(3, value).BackColor = Color.Red Then
                        MsgBox("sfd")
                    End If
                Next
            Case 4
                For value As Integer = 1 To 4
                    If graph(4, value).BackColor = Color.Red Then
                        MsgBox("sfd")
                    End If
                Next
            Case Else
                Debug.WriteLine("Not between 1 and 10, inclusive")
        End Select
    Next
End Sub

Private Sub PictureBox1_Click(sender As System.Object, e As System.EventArgs) Handles PictureBox1.Click
    PictureBox1.BackColor = Color.Red
End Sub

Any Help is greatly appreciated. Thank you!

Upvotes: 0

Views: 1922

Answers (2)

Nico Schertler
Nico Schertler

Reputation: 32607

Before I answer your question, here is some general advice regarding your code:

VB array indices are zero-based. An array Dim arr(4) As ... declares an array with five elements (which can be accessed by index 0 through 4). Therefore, your array declaration of graph creates an array with 25 elements when you only need 16. Such waste of memory should be avoided.

The creation of your graph could be automated. It's probably even a better idea to create all picture boxes automatically. This way, if you want to change the graph size, you just have to change a single number instead of a whole bunch of code. Similarly, the bounds of your for loops should respect the actual array bounds instead of some pre-defined constants.

When you parse user input, you should handle incorrect input. Use Integer.TryParse() instead of CInt().

As a beginner, you should turn Option Strict On (via the project settings). This avoids narrowing implicit casts that you might not be aware of. E.g. it would tell you that 60000 / tempo results in a Double and by assigning that to an Integer variable you will loose precision.

I suspect that you have similar click handlers for all picture boxes. If all handlers are doing the same work, use a single handler. The method's sender argument tells you which picture box was clicked (you can cast it to the appropriate type).

Using a For loop does not make any sense if you split the body according to the loop variable. If you do different work in every iteration, don't use a loop at all and just write the code snippets after each other. However, in your case, a loop makes sense, though not as you used it. See next section for more information.

Now to your question. If you want to gather the checked boxes per row, you should use two nested loops. The outer loops iterates the rows and the inner loop iterates columns. Before starting the inner loop, you should reset a buffer that holds the indices of the checked boxes. I use the corrected indices (0 through 3). Furthermore, I assume that the first index in the graph array specifies the row and the second specifies the column. If that's wrong, you just have to swap the according pieces of code:

Dim checkedBoxes As New List(Of Integer) 'holds the indices of checked boxes in a row
For row As Integer = 0 To graph.GetUpperBound(0)
    checkedBoxes.Clear()
    For col As Integer = 0 To graph.GetUpperBound(1)
        ...
    Next
    'Now report the checked boxes.
    MessageBox.Show("Checked boxes of row " & row & ":" & Environment.NewLine & _
         String.Join(", ", checkedBoxes))
Next

The String.Join method is used to concatenate the list of column indices to a single string, separated by ,.

Now we just need to add code to the loop body that gathers the checked boxes:

If graph(row, col).BackColor = Color.Red Then
    checkedBoxes.Add(col)
Next

That's all. No awkward Switch statement, no duplicate code. There are still some improvements that could make this code more efficient, but I'll leave it with this for now.

Upvotes: 2

Daniel Baron
Daniel Baron

Reputation: 34

if you want two message boxes to appear at the same time, the only way would be to run them on different threads, ie after the conditional create a thread that runs the message box to keep the loop going. A message box will halt the code on that thread and waits for user input and the only way you can run 'msgbox()' at the same instant is with multiple threads. Otherwise what you are asking is impossible.

Upvotes: 0

Related Questions