Randomly Generating a Number between x and y-VBForums

# Thread: Randomly Generating a Number between x and y

1. ## Randomly Generating a Number between x and y

Basically I made a game but one of the most important parts I can't program because I'm just an average programmer.

What I need help with is creating a function that randomly generates numbers between x and y. X being 1 and y being 15. It will then use these randomly generated numbers and assign them to my 15 buttons. So instead of the buttons being labeled 1-15 in order, it'll be all mixed up and randomized.

2. ## Re: Randomly Generating a Number between x and y

Do you want the numbers 1 to 15 to be assigned randomly or do you want a random number in each button text?
I am assuming it is the first option.
My method would be to create a List. Fill it with the numbers 1 to 15 in ascending order.
Generate a random number between 1 and 15
Code:
```Dim myint As Integer
Dim num As New Random
myint = num.Next(1, 15)```
assign that to the first button text and remove that entry in your list of numbers.
Then, take a random number between 1 and 14 and repeat until the list is empty.
You could use a loop
Code:
```For counter = 15 to 1 step -1
myint = num.Next(1, counter)
'Assign result to Button.Text
'Delete entry myint in the list
Next counter```

3. ## Re: Randomly Generating a Number between x and y

The word "between" is not used precisely by many people when it comes to ranges. Strictly speaking, when you "between X and Y" you mean greater than X and less than Y. If you want to include both X and Y then you should say "from X to Y" or perhaps "in the range X to Y inclusive". It's also worth noting that the minValue parameter of the Random.Next method is inclusive while the maxValue parameter is exclusive, which means that Random.Next(X, Y) will return a number N in the range X <= N < Y.

As for the question, it appears to me that you want a unique random in the range 1 to 15 inclusive on each of your Buttons. It's a little more advanced because it uses LINQ but I would tend to put the Buttons into an array and then randomise that, then display each Button's index on that Button, e.g.:
vb.net Code:
`Dim rng As New RandomDim buttons = Controls.OfType(Of Button)().OrderBy(Function(b) rng.NextDouble()) For i = 0 To buttons.GetUpperBound(0)    buttons(i).Text = (i + 1).ToString()Next`

4. ## Re: Randomly Generating a Number between x and y

As I've said above I'm just average. When it comes to speaking programming I'm not the best at it so I apologize for saying between X and Y. As I do want 1 and 15 included. Now I'm not just looking for an answer where I can just copy and paste. I really want to understand the code I'm putting into my program, otherwise I feel like I'm just stealing it.

@espaņolito, I think I understand your method a lot more than jmcilhinney's code. But if either one of you could show all the code I would need to make this shuffle option work and explain how the code works, I would appreciate it so incredibly much.

I'm putting this shuffle code in the form load up sub, so when the game loads all 15 buttons have random numbers assigned as their text.

5. ## Re: Randomly Generating a Number between x and y

Here's a very simple 'shuffle' that will do the job. It works by moving randomly chosen items from one list to another.

vb.net Code:
`Dim RdI As New Random        Dim idx As Int16        Dim LofI As List(Of Int16) = New List(Of Int16) From {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} ' the value range        Dim Shuffle As List(Of Int16) = New List(Of Int16)   'empty list         For i = LofI.Count To 1 Step -1            idx = RdI.Next(1, i) - 1 'pick a random item            Shuffle.Add(LofI(idx))   'copy it to the new list            LofI.RemoveAt(idx)       'remove it from the original list        Next                         'until original list is empty         Dim buttons = Controls.OfType(Of Button)()        For i = 0 To Shuffle.Count - 1            buttons(i).Text = Shuffle(i).ToString 'add shuffled list values to buttons in order        Next`

6. ## Re: Randomly Generating a Number between x and y

My submission is below, which works, albeit rather longwinded.
Code:
```    Private Sub FillBtns()
Dim ctr As Integer = 0
Dim num As New Random
'you now make a list of the numbers you want to use
Dim nbrs As New List(Of Integer)
For ctr = 1 To 15
Next
Dim btns As New List(Of Button)
Dim myint As Integer = 0
'Now you make a list containing your buttons
For Each button In Me.Controls
Next
For counter = 15 To 1 Step -1
'this starts with the last button in the list and works its way to the front assigning numbers as it goes
'each time you choose a number from your list of numbers, you delete it so it can't be chosen again
'that is the reason for the counter stepping -1
myint = (num.Next(0, counter - 1))
'Assign result to Button.Text
btns(counter - 1).Text = nbrs(myint)
'Delete entry myint in the list
nbrs.RemoveAt(myint)
Next counter
End Sub```
I tried JmC's code and it refused GetUpperBound saying it was not valid,I can't remember exactly why. I replaced it with a hard-coded 15 and it almost worked. Some of the buttons did not receive an assignment.

It seems, Dunfiddlin's code does it pretty much how I suggested, but a LOT tidier than mine!

7. ## Re: Randomly Generating a Number between x and y

You might already know that random numbers are not truly random. I found this link which uses system clock ticks as a seed which increases the randomness.
Or you could just use Randomize. It all depends on just how random you need it to be.

8. ## Re: Randomly Generating a Number between x and y

@dunfiddlin, I went with your code first because it looked like I could understand it the most. But when I tested it, it repeats values.
@espaņolito, I went with your code second and it also repeats values.

Any help?

9. ## Re: Randomly Generating a Number between x and y

Originally Posted by Providence
@dunfiddlin, I went with your code first because it looked like I could understand it the most. But when I tested it, it repeats values.
@espaņolito, I went with your code second and it also repeats values.

Any help?
Er ... my code most certainly does not repeat values. It is in fact impossible for it to do so. If your adaptation of it does repeat values then I suggest that you post it so we can see what you changed!

10. ## Re: Randomly Generating a Number between x and y

Screenshot of code in action:

Code in my source:
Code:
```Private Sub ShuffleBoard_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim RdI As New Random
Dim idx As Int16
Dim LofI As List(Of Int16) = New List(Of Int16) From {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} ' the value range
Dim Shuffle As List(Of Int16) = New List(Of Int16)   'empty list

For i = LofI.Count To 1 Step -1
idx = RdI.Next(1, i) - 1 'pick a random item
Shuffle.Add(LofI(idx))   'copy it to the new list
LofI.RemoveAt(idx)       'remove it from the original list
Next                         'until original list is empty

Dim buttons = Controls.OfType(Of Button)()
For i = 0 To Shuffle.Count - 1
buttons(i).Text = Shuffle(i).ToString 'add shuffled list values to buttons in order
Next
Button16.Text = ""
End Sub```

11. ## Re: Randomly Generating a Number between x and y

Originally Posted by espaņolito
You might already know that random numbers are not truly random. I found this link which uses system clock ticks as a seed which increases the randomness.
Or you could just use Randomize. It all depends on just how random you need it to be.
That doesn't increase the randomness. If you use the Random constructor with no parameters then it will use the system time as a seed anyway, so providing a time-based seed yourself is pointless. The only time there's a need, a need for see (sorry, couldn't resist) is when you're creating multiple Random objects possibly in quick succession and therefore the system clock will not change sufficiently to provide a different seed each time, in which case you must provide your own seed that you can ensure is different each time.

As for using Randomize, blurgghh!! Randomize is used in conjunction with Rnd but we're not using VB6 so we don't use either.

12. ## Re: Randomly Generating a Number between x and y

So is there no way not to repeat numbers? Because I get a repeated number almost every time.

13. ## Re: Randomly Generating a Number between x and y

Your problem is you have 16 buttons on your form, but you only mentioned 15 in your original post.

I suspect Button1 has text set to "1" in the designer and your repeated number is always 1.

The code you are using modifies the text of buttons 2 through 16, leaving Button1's text as it was originally set i.e. "1". You then clear the text on button 16 which only has a 1 in 15 chance of being "1" and so you have a 14 in 15 chance of ending up with two "1"s (I think; I always sucked at stats).

This is because the buttons collection contains 16 buttons while the list of shuffled numbers only contains 15 items. The code updates the text of the first 15 buttons from the buttons collection. However, the buttons are added to that collection in the same order that they are added in code to the form's controls collection behind the scenes (in the form's Designer.vb page of code). That order is normally the reverse of the order that you added them to your form in the IDE's designer window (although it can be changed under certain circumstances). Thus, the first 15 buttons will be Button16 through Button2 and they are the ones that have the random numbers assigned to their Text properties.

A quick fix would be to remove Button16 from your code's buttons collection after you populate it.

Change
Code:
`Dim buttons = Controls.OfType(Of Button)()`
to
Code:
```Dim buttons As List(Of Button) = Me.Controls.OfType(Of Button)().ToList
buttons.Remove(Button16)```

14. ## Re: Randomly Generating a Number between x and y

I checked Dunfiddlin's code against yours. One thing you have changed is
Button16.Text=""
If you change this to
Button1.Text=""
You will find his code works perfectly.
As Inferrd says, you most likely have button1.Text already set to display "1"

@JmC, thanks for the clarification, also that all things legacy VB6 are blurgghh! Must remember I'm swimming with the Big Boys now.

15. ## Re: Randomly Generating a Number between x and y

There is also a bug in the shuffling code...
idx = RdI.Next(1, i) - 1 'pick a random item
Should be...
idx = RdI.Next(0, i) 'pick a random item

The original code chooses an random index that never includes the last item in the list. This means that the last item left in the list will, in this case, always be 15 and so the first item in the shuffled list will always be 15.

This also helps to highlight the bug that Inferred and espaņolito are talking about as your screen shots show the second button as 15 not the first.

16. ## Re: Randomly Generating a Number between x and y

Originally Posted by Milk
The original code chooses an random index that never includes the last item in the list. This means that the last item left in the list will, in this case, always be 15 and so the first item in the shuffled list will always be 15.
This also helps to highlight the bug that Inferred and espaņolito are talking about as your screen shots show the second button as 15 not the first.
Not sure about this because in my code, on further testing, I noticed that that exact thing happens every time (TextBox15.Text is always 15) and I am using a base of 0
myint = (num.Next(0, counter - 1))
There must be another reason, though I am at a loss .

17. ## Re: Randomly Generating a Number between x and y

At a guess num.Next(0, counter - 1) should be just num.Next(0, counter) (or just num.Next(counter) .)

Remember the Maximum parameter with Random.Next(minimum, maximum) is exclusive.

18. ## Re: Randomly Generating a Number between x and y

num.Next(0, counter)
solved it. So it was a case of same error, different way to get it

19. ## Re: Randomly Generating a Number between x and y

Originally Posted by Milk
There is also a bug in the shuffling code...
idx = RdI.Next(1, i) - 1 'pick a random item
Should be...
idx = RdI.Next(0, i) 'pick a random item

The original code chooses an random index that never includes the last item in the list. This means that the last item left in the list will, in this case, always be 15 and so the first item in the shuffled list will always be 15.
Shows how often I use random numbers! Mind you, when apart from MS VB would you ever encounter a MinValue that's inclusive and a MaxValue that's exclusive! Shouldn't the IDE call it OneMoreThanMaxValue or something?

20. ## Re: Randomly Generating a Number between x and y

I want to personally thank all of you for your help, the code is working now. But I still don't completely understand the code where I could use it, remember it, and use it if I ever needed it again. Could someone take the time to explain the code to me? Speak to me as if I am a student and you're my teacher?

Code:
```Dim RdI As New Random
Dim idx As Int16
Dim LofI As List(Of Int16) = New List(Of Int16) From {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} ' the value range
Dim Shuffle As List(Of Int16) = New List(Of Int16)   'empty list

For i = LofI.Count To 1 Step -1
idx = RdI.Next(1, i) - 1 'pick a random item
Shuffle.Add(LofI(idx))   'copy it to the new list
LofI.RemoveAt(idx)       'remove it from the original list
Next                         'until original list is empty

Dim buttons = Controls.OfType(Of Button)().ToList
buttons.Remove(Button16)
For i = 0 To Shuffle.Count - 1
buttons(i).Text = Shuffle(i).ToString 'add shuffled list values to buttons in order
Next```

Any one?

22. ## Re: Randomly Generating a Number between x and y

I hope I didn't step on your toes dunfiddlin by explaining your code.
Is this OK Providence?

Define variable called RdI as a Random Type variable.
Code:
`Dim RdI As New Random`
Define a List Variable to hold the integers that you need before shuffling.
Code:
`Dim LofI As List (Of Int16) = New List (Of Int16) From {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}`
Create a new list ready to hold the shuffled numbers
Code:
`Dim Shuffle As List(Of Int16) = New List(Of Int16)`
LofI.Count gives the number of entries in the list LofI. We repeat this number of times. We have to go backwards in the loop (Step -1) because we will be deleting one from the list every time it loops.
The loop consists of:
Take a random number based on the maximum number of entries in the list
Use that number as an index in the list of integers (LofI) and add the value in that index to the list of shuffled numbers
Remove the integer we used from the list of integers LofI so that it cannot be selected again. (This is why dunfiddlin said his code (and mine) could never repeat an integer)
Code:
```For i = LofI.Count To 1 Step -1
Idx=RdI.Next(1,i) -1
LofI.RemoveAt(idx)
Next```
We are now in a position where we have all the integers in the original list in a random order in the new list Shuffle.

Create an array of the buttons on the form
Code:
`Dim buttons = Controls.OfType(Of Button) ().ToList`
Remove Button 16 because you only need to use 15 of them
Code:
`Buttons.Remove(Button16)`
We now only need a simple For-Next loop because the numbers in the list are now random. It takes each each entry in the list in turn and sets the respective button text accordingly.
Code:
```For i = Shuffle.Count – 1
Buttons(i).Text = Shuffle(i).ToString
Next```

23. ## Re: Randomly Generating a Number between x and y

Thanks espaņolito! I think I understand it, what do you think?

Code:
```        Dim MyRandom As New Random
Dim ChosenNumber As Int16
Dim NonShuffledList As List(Of Int16) = New List(Of Int16) From {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} ' the value range
Dim ShuffledList As List(Of Int16) = New List(Of Int16)   'empty list

For AddToShuffledList = NonShuffledList.Count To 1 Step -1
ChosenNumber = MyRandom.Next(1, AddToShuffledList) - 1 'pick a random item
ShuffledList.Add(NonShuffledList(ChosenNumber))   'copy it to the new list
NonShuffledList.RemoveAt(ChosenNumber)       'remove it from the original list
Next                         'until original list is empty

Dim buttons = Controls.OfType(Of Button)().ToList
buttons.Remove(Button16)

For AssignButtonText = 0 To ShuffledList.Count - 1
buttons(AssignButtonText).Text = ShuffledList(AssignButtonText).ToString 'add shuffled list values to buttons in order
Next```

24. ## Re: Randomly Generating a Number between x and y

Looks like you've got it to me

25. ## Re: Randomly Generating a Number between x and y

Or:
vb.net Code:
`Dim rng As New RandomDim buttons = Controls.OfType(Of Button)().                       Except({Button16}).                       OrderBy(Function(b) rng.NextDouble()).                       ToArray() For i = 0 To buttons.GetUpperBound(0)    buttons(i).Text = i.ToString()Next`

26. ## Re: Randomly Generating a Number between x and y

Oops! I do believe the OP wanted 1-15 not 0-14! Also there was a stipulation that the code be explained so that it could be understood and, more importantly, remembered. Would it kill you to descend to the level of normal human beings once in a while and make your code explicable? I'm sure that there are a lot of people here who will have no idea how or why OrderBy(Function(b) rng.NextDouble()) works.

27. ## Re: Randomly Generating a Number between x and y

Don't you think that the shorter and more concise code becomes, the harder it becomes to understand? I am one of those who has absolutely no idea how OrderBy(Function(b) rng.NextDouble()) works but that solution is exceptionally elegant, it must be said.

However a bit of "Googling" and I found it's LINQ. An explanation here

28. ## Re: Randomly Generating a Number between x and y

jmcilhinney's code may be short but I don't understand anything about it, nor would I remember it. In the end, my favorite people here are espaņolito and dunfiddlin.

@espaņolito Thank you for the explanation, you really helped me.
@dunfiddlin Thank you for the awesome code.

29. ## Re: Randomly Generating a Number between x and y

Originally Posted by dunfiddlin
Oops! I do believe the OP wanted 1-15 not 0-14! Also there was a stipulation that the code be explained so that it could be understood and, more importantly, remembered. Would it kill you to descend to the level of normal human beings once in a while and make your code explicable? I'm sure that there are a lot of people here who will have no idea how or why OrderBy(Function(b) rng.NextDouble()) works.
Well my whiny friend, given that I explained the code back in post #3, I didn't feel the need to explain it again. Would it kill you to descend to the level of normal human beings and read my first post once in a while? The only real difference between my latest code and the code in post #3 is the use of Except and pardon me if I thought that the meaning of Except would be obvious to anyone with a basic understanding of the English language. There was also a mistake in my original code, i.e. I missed ToArray, and there was a mistake in my latest code, i.e. I missed the (i + 1). Sorry to offend someone like yourself who obviously never makes a mistake. I said back in post #3 that the code I provided was more advanced and utilised LINQ. I didn't say that anyone had to use it and I'm not about to explain the ins and outs of lambda expressions when anyone who understands LINQ will understand it and anyone who doesn't can either ignore it or make the effort to learn about LINQ. I have lost count of the number of times that I have posted code and provided additional information that has simply been ignored so do not come in here and tell me that I never explain my code. You may think that you've seen it all and know it all but you have not and do not.

30. ## Re: Randomly Generating a Number between x and y

Originally Posted by Providence
jmcilhinney's code may be short but I don't understand anything about it, nor would I remember it. In the end, my favorite people here are espaņolito and dunfiddlin.
That can be quite true. That said, you didn't have to search anywhere to find that it was LINQ because I said that it is back in post #3. If you understand LINQ then what's going on there is fairly obvious and if you don't understand LINQ then it's not. I'm not about to start explaining all the details of LINQ so anyone who doesn't understand it is free to ignore it or investigate LINQ for themselves.

31. ## Re: Randomly Generating a Number between x and y

Yeah I don't know anything about LINQ, that's why I like dunfiddlin's code more.

32. ## Re: Randomly Generating a Number between x and y

Originally Posted by Providence
Yeah I don't know anything about LINQ, that's why I like dunfiddlin's code more.
I have no issue with your not wanting to use the code because you don't understand it or not wanting to learn about LINQ at this stage. That doesn't mean that you won't benefit though, as now you know that LINQ exists and you have an idea how it might be used, so you're one step closer to using it. Also, there may be others who read this thread and can benefit from it. Any sensible .NET developer will learn to use LINQ before too long as it is a very powerful technology that makes many things simpler; sometimes very complex things very simple. Some of those developers will even be able to visit MSDN and read for themselves what a method does rather than demanding that someone else explain every little detail. Just to be clear, I'm not referring to you when I say that.

33. ## Re: Randomly Generating a Number between x and y

I recently used something like this; the Rnd()*15 part gives you a random decimal number times 15, which results in something bigger than 0 and less than 15. Then the Int function of that gives the greatest integer less than the decimal, so now you have an integer from 0 to 14 inclusive. Add one to get a number from 1 to 15.

Dim RanNum As Integer
RanNum = Int(Rnd() * 15) + 1 'produces a random integer from 1-15

34. ## Re: Randomly Generating a Number between x and y

Originally Posted by deejay41
I recently used something like this; the Rnd()*15 part gives you a random decimal number times 15, which results in something bigger than 0 and less than 15. Then the Int function of that gives the greatest integer less than the decimal, so now you have an integer from 0 to 14 inclusive. Add one to get a number from 1 to 15.

Dim RanNum As Integer
RanNum = Int(Rnd() * 15) + 1 'produces a random integer from 1-15
That's bad VB.NET code. There are a large number of people who still teach that because of their VB6 roots but it is not the way it should be done in VB.NET. If you want to write VB6 code then go use VB6. If you're going to use VB.NET then use it. In any .NET language, the most correct way to generate random numbers for everyday use is to create an instance of the Random class and call Next, NextDouble or NextBytes, depending on what type of number(s) you want. That's it, that's all.

35. ## Re: Randomly Generating a Number between x and y

Originally Posted by Espaņolita
Don't you think that the shorter and more concise code becomes, the harder it becomes to understand? I am one of those who has absolutely no idea how OrderBy(Function(b) rng.NextDouble()) works but that solution is exceptionally elegant, it must be said.

However a bit of "Googling" and I found it's LINQ. An explanation here
Originally Posted by Providence
Yeah I don't know anything about LINQ, that's why I like dunfiddlin's code more.
Then i think you should take the time to learn LINQ, it's easily picked up and very powerful, but also because dunfiddlins example is also using LINQ. Enumerable.OfType(Of TResult) Method is from the LINQ namespace.

36. ## Re: Randomly Generating a Number between x and y

You could also use a quick and easy alternative to random.

vb Code:
`Public Class Form1     Private Sub Example()        Dim numbers As New List(Of Integer)(Enumerable.Range(1, 15))        Dim buttons = Controls.OfType(Of Button)().                       Except({Button16}).                       OrderBy(Function(b) Guid.NewGuid()).                       ToArray         For i = 0 To buttons.GetUpperBound(0)            buttons(i).Text = i.ToString()        Next    End Sub End Class`

37. ## Re: Randomly Generating a Number between x and y

OK, I'm not very experienced, so I didn't know my code was reminiscent of VB6, which I have never used. I'm curious as to why it's "bad" code; I found this method used in James Foxall's book Visual Basic.NET, and I liked the method because the mathematical logic is obvious in the code, and it's brief.

38. ## Re: Randomly Generating a Number between x and y

Originally Posted by deejay41
OK, I'm not very experienced, so I didn't know my code was reminiscent of VB6, which I have never used. I'm curious as to why it's "bad" code; I found this method used in James Foxall's book Visual Basic.NET, and I liked the method because the mathematical logic is obvious in the code, and it's brief.
It's no more brief than using the Random class and, if you use Random, there is no mathematical logic. If you've never used VB6 then you shouldn't even know about that Rnd function because you should have learned the .NET way to generate random numbers but, as I said, a large number of VB.NET developers who have graduated from VB6 have failed to upgrade their knowledge and, more importantly, their teaching. Stuff like Randomize and Rnd, while still quite legal in VB.NET, have been included for two primary reasons: make VB6 developers feel comfortable enough to use VB.NET and to allow VB6 code to upgrade with a minimum of issues. If there's a way to do something in VB.NET that didn't exist in VB6 then there's probably a good reason for it.

39. ## Re: Randomly Generating a Number between x and y

Thank you.

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•