I have been working on a school project that is to randomly select 14 names from a class (of 33) and place them in a list box.

My thinking behind it was to create an array that would randomly select 14 numbers from 1 to 33 and then use a Select Case statement to convert the numbers to names . . . however I am failing. I have tried putting the case statement in both the list box and in other places but cannot seem to fathom where it is I am going wrong.

Can anyone offer any advice?

Public Class Form1
    Dim iNumber As Integer
    Dim arrNumber(0 To 13) As Integer

    Public Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        ProgressBar1.Maximum = 28
      End Sub

    Private Sub bRandom_Click(sender As System.Object, e As System.EventArgs) Handles bRandom.Click
        Dim x, y, z As Integer

        For x = 0 To 13
stage1:
            Randomize()
            iNumber = Int((33 * Rnd()) + 1)
            For y = 0 To 13
                If iNumber = arrNumber(y) Then
                    GoTo stage1
                ElseIf arrNumber(13) > 0 Then
                    GoTo stage2
                End If
            Next y
            arrNumber(x) = iNumber.ToString
            ProgressBar1.Increment(1)
        Next x
stage2:
        For z = 0 To 13
            LBOSCEStations.Items.Add(arrNumber(z))
            Select Case iNumber
                Case 1
                    arrNumber(z) = "Harry"
                Case 2
                    arrNumber(z) = "Sally"
                Case 3
                    arrNumber(z) = "Billy
            End Select
        Next

    End Sub

End Class

You can declare the list as

Dim names As New List(Of String) From {"John", "Fred", "James", "Jen", "Archie", "Brenda", "Melissa"}

Use the random number generator to get a new random number from min=0 to max=names.Count. Because max (at least according to Microsoft) is actually one more than the actual max (rand.Next(0,10) actually generates a number from 0 to 9), you don't have to worry that Count actually is an index one greater than the largest index.

Once you get a list index, remove that name from the list. That will ensure unique names are chosen. If List(Of String) is not suitable then make the list of whatever type you are using.

Edited 4 Years Ago by Reverend Jim: n/a

Rather create a List<T> where T is a class object (student name, ...)

Will I still be able to assign each name a specific number, I am curious to know because I know that next weeks project will be an extension of this where we'll be asked to add some filters to the random name thingy . . . filters like Don't select names that start with "A" and so I was planning on working some if statement out that would make it regenerate the random number if it fell within the random number range of "A"

If that makes sense

(still reading up on lists)

HEre s the code exampe, a mid more sophisticated:

Dim r As New Random()
Dim students As New List(Of Student)()
'I will create 33 stdents in a loop (you fil them your way...)
For i As Integer = 1 To 33
	Dim s As New Student()
	s.Id = i
	s.Name = "Student Name " & i
	s.bSelected = False
	students.Add(s)
Next
'now select 14 random student:
Dim selectedStudents As New List(Of Student)()
For i As Integer = 0 To 13
	While True
		Dim index As Integer = r.[Next](0, students.Count)
		If Not selectedStudents.Contains(students(index)) Then
			selectedStudents.Add(students(index))
			Exit While
		End If
	End While
Next

'prove of selected students:
Dim sb As New StringBuilder()
For i As Integer = 0 To selectedStudents.Count - 1
	sb.AppendLine(String.Format("{0}. ID: {1}, name: {2}", i + 1, selectedStudents(i).Id, selectedStudents(i).Name))
Next
Console.WriteLine(sb.ToString())
Console.ReadLine()

If you need to pair a name with a number you could use a dictionary instead of a list. The syntax is

Dim namelist as New Dictionary(Of Integer, String) From { _
       {1, "Fred"},   _
       {2, "George"}, _
       {3, "Amy"}     _
    }

If you have filters you could add a test in the loop that checks a name after it is selected. If the name is unsuitable then remove it from the dictionary and generate a new selection.

Because this is for an assignment I thought it was more appropriate to provide suggestions rather than a complete solution.

If you need to pair a name with a number you could use a dictionary instead of a list. The syntax is

Dim namelist as New Dictionary(Of Integer, String) From { _
       {1, "Fred"},   _
       {2, "George"}, _
       {3, "Amy"}     _
    }

If you have filters you could add a test in the loop that checks a name after it is selected. If the name is unsuitable then remove it from the dictionary and generate a new selection.

Jim, with this method, would I be able to generate a random number into an array (as I have done in my current code) and then have it add the String section of the name to the ListBox? Or have I barked up the wrong tree with my original code and should I start over?

This is the most simpliest random number selection (form 1 to 33 - take 14 random numbers):

Dim r As New Random()
Dim listOfNums As New List(Of Integer)()
For i As Integer = 1 To 33
	While True
		Dim num As Integer = r.[Next](1, 34)
		If Not listOfNums.Contains(num) Then
			listOfNums.Add(num)
			Exit While
		End If
	End While
Next

If you want to be able to index then you should use a list rather than a dictionary. If you want to maintain a correlation between a name and a number then you could create a structure consisting of a name/number pair, then create a List(Of Integer, MyStruct). That way, you could generate a random number from (0,MyList.Count). Whether or not the selected name passes the filters (whatever they may be) then you could remove it from the list to prevent it from being selected again. You could maintaine a similar (but separate) list of the same composition, but called something like SelectedNames. If the name passes the filter test then remove it from the original list and add it to the selected list. Stop when you either run out of names in tthe original list or you have a sufficient number of names in the selected list.

I am just trying to get my head around this all. Its pretty new stuff, certainly nothing we have covered in class :/

What I am trying to understand is, why can I not (for example) have say 14 textbox that each index of the array correspond to, with a case statement saying if tb1.text = 1 then tb1.text = "Harry"

hide those text boxes and populate to a list a box?

in my head that seems more simple than this list business (that is because I have not really studied it and any resources online talk about it in a way that only people who know about them would understand.

Don't get me wrong, i am not asking for anyone to do this for me, I just want to full understand all possible options before I go ahead an teach myself something new

It's best when you have a list of things that are all going to be treated equally to process them in a loop. Doinig it your way is referred to as the brute force method. For example, if you had a list of five numbers you wouldn't do the following to calculate the sum:

sum = numbers(0)
sum += numbers(1)
sum += numbers(2)
sum += numbers(3)
sum += numbers(4)

If you do groups of things in loops then it is easier to adapt the program when the number of items changes. If you create a form with 14 textboxes and set their values then everything works fine. But if you want to add a few names then you have to edit the code, resize the form and add textboxes (and more code). If instead you have a list of names in a file and contain them in a listbox then all you need to do is edit the list of files. No code or form changes and no recompiling.

Ok. I can see that as a benefit, another thought that came to me, is there a way in which I can take the random numbers generated in my array to then be used to fetch the names saved in the list via their index number(?)

For example:

Arrnumber(0) is 10

which then gets NameList(10) as Harry

Even still, could I put the names in an Array as well, so then it would be exactly the same as above but this time it would remove the name from the array and then put it in the list, which would then populate the ListBox . . . or am I starting to venture into the realms of stupidity?

It's hard to answer that without a clearer idea of what you want. If you want to associate a name with a specific number (like a student ID or SSN) the a structure (or a class) with two properties (name and ID) is appropriate. I don't understand why it is necessary to associate a random number with a name when the random number's purpose is only to ensure a random name selection. In any case, if you use a List and generate a random number (0,List.Count) then the random number is the index into the list. You should use a List rather than an Array to avoid having to redim.

This article has been dead for over six months. Start a new discussion instead.