On a form, I have text box called “txtnum”. As can be seen in the code below, when I press a certain button a random number between 0 and 311 will appear in the textbox. What I need to be able to do though, is make sure that once a certain number has appeared, it won’t appear again until I tell it to. Can someone please tell me how to do this in Layman’s terms. (I am new at this.)
I can’t express this in VB 'cos I don’t use it but here is one solution:
[ol]
[li]Create an array of 312 integers.[/li][li]Initialize said array with values 0 to 311[/li][li]Initialize an integer ‘n’ to 311[/li][li]On each press of the button:[/li][list=a]
[li]generate a random number ‘r’ in range 0 to n[/li][li]use value in position ‘r’ as the result value[/li][li]swap values at positions ‘r’ and ‘n’ in array[/li][li]decrement ‘n’. The mos recent value is now at ‘n + 1’ and will not be available on next go[/li][/ol]
[li]reset ‘n’ to 311 to reset[/li][/list]
This assumes that your array is indexed from 0 to 311, as it would be in C or C++ for example.
When I said “I am new to this” it meant that I don’t know much about it. What I really need is the code that has to be typed in, I don’t even know what an “array” is. But thanks for your help anyway.
I don’t have a VB program with me right now but I might be able to burn my brain and come up with something. and just so you know an array is basically a list of items like apples, oranges, bannanas or numbers, it’s what ever you want to put in this list it looks kinda like this
array
x(0)=apple
x(1)=orange
x(2)=bannana
and if you asked for what was in x(1) you’d get back orange it makes things easier to organize instaed of having to make new variables for everything.
I’d do the program something like this:
Create the array for 310 objects, VB starts at 0 so 0 to 310 is 311 objects.
Fill each object of the array and after filling each number have it check the rest of the array to see if it has come up before and if it has have it regenerate a new number.
it would look something like this but I could be wrong in some areas.
Dim NumberArray(310)
Dim x
Dim y
For x = 0 to 310
NumberArray(x) = Funtion for Random number (sorry I don’t remember how to do this)
for y = 0 to x
if Numberarray(x)=Numberarray(y) then
numberarray(x)= get new random number
next y
next x
This should pretty much work to fill the array and then all you’d have to do is for every button push move to the next number in the array something like this:
Sub Button_Click()
static z
txtbox.text=numberarray(z)
z=z+1
end sub
if you need more help let me know. I hope I got most of it right.
EtheH, if I understand your code correctly I think there is a bug where you state
I assume this is here to spot and regenerate duplicates. The problem as I see it is that you only get one try at generating a new value with no check to ensure that this is not also a duplicate. As you get past half way it becomes more likely that the new number will also be a duplicate than not.
Also, having a loop within a loop means that the work required to do this is proportional to the square of the number of values. This would get inefficient very fast if you decide to increase the range much above the 312 stated.
Not being VB literate I beg forgiveness if I misunderstand the code.
If you don’t want to work with arrays, and you don’t mind a sloppy program, the easiest way to do it would be to simply save the value you got in a variable. Then put in an IF statement that says if you get that number again, randomize again and get a new number.
Of course, if you need to save multiple values, it will get more complicated and the array method the posters above mentioned might be better.
Ok…I’m going to assume you really aren’t worried about the performance drawbacks of using two loops (using two loops makes it a lot easier to right the code for this, and if you were really worried about performance you’d probably be studying C++ rather than VB)
Anyway, here’s the code for it (the textbox I used is “Text1”). If you need to repeat a certain number, then just store the value of “intCtr” in a seperate variable.
I did most of the code in the Form_Load event, but you should probably set up a standard module, and then put the code in a “Sub Main”, which will run when the program starts up.
Option Explicit
Private randoms() As Integer
Public intCtr As Integer
Private Sub Command1_Click()
Text1.Text = randoms(intCtr)
intCtr = intCtr + 1
End Sub
Private Sub Form_Load()
Dim i As Integer
Dim i2 As Integer
Dim blnFlag As Boolean
ReDim randoms(311)
Randomize
For i = 0 To 311
If blnFlag = False Then
randoms(i) = Int(312 * Rnd)
For i2 = 0 To i
If randoms(i2) = randoms(i) Then
blnFlag = False
Exit For
Else
blnFlag = True
End If
Next
End If
Next
A couple of secondary issues here – If you want true randomness, you need to be willing to accept duplicates.
Is there an effcetive means for recyclying the list? You say you don’t want a number to be re-used until you say so, but can you guarantee that you will say so within a reasonable number of uses. As the number of filled cells in the array gets higher, the longer it will take to find a number that hasn’t been used. Take the extreme case where 0 thru 310 have been used and we have to sit and generate random numbers until 311 comes up – that could take a long time.
This is application dependent and might never be a problem, but you might want to consider some preset point at which the list would recycle if it isn’t done manually, say after 50 numbers are used, the list will be cleared to start afresh.
no you got it right on the nose. I wrote it pretty quick and did it all in one procedure so he could understand. not very good really. I didn’t think about it not checking for the second one, I might have caught that if I was actually doing it. I know it would also take a lot of memory/time etc to do it that way but I really don’t know any other way to do it as I don’t program much anymore and haven’t done it in over a year. but hey MadHatter didn’t ask for nice and quick, just to work!
Ticker’s first solution is the proper one. You most definitely don’t want to keep an array of the numbers already generated and force the program to check it and re-generate a random number if it finds the last one. Doing that will be wildly inefficient. Especially when you get down to the last few numbers. Now you are essentially forcing the computer to generate thousands of random numbers before it hits an unused one.
Perhaps the best way to do this is to write an algorithm similar to shuffling a deck of cards, except that this ‘deck’ has 312 items in it. (Sounds like a 6-deck blackjack shoe).
You should be able to find card-shuffling algorithms all over the net.
Most people here are going to be hesitant to publish code you can just plug-in and run, because A) you should be learning it yourself, and B) a lot of requests like this come from kids in school who have class projects, or college students who have a lab to hand in, and we shouldn’t be a forum for solving your homework for you.
So expect people to help with general concepts and to answer specific questions about techniques, but it’s not really a good idea to come here and say, “Will someone write this function for me?”
I actually left something out of the code that I posted earlier…so anyway, here’s the version that will actually make sure there are no duplicates:
Option Explicit
Private randoms() As Integer
Public intCtr As Integer
Private Sub Command1_Click()
Text1.Text = randoms(intCtr)
intCtr = intCtr + 1
End Sub
Private Sub Form_Load()
Dim i As Integer
Dim i2 As Integer
Dim blnFlag As Boolean
ReDim randoms(311)
Randomize
For i = 0 To 311
randoms(i) = Int(312 * Rnd)
Do Until blnFlag = True
If i = 0 Then Exit Do
For i2 = 0 To i - 1
If randoms(i2) = randoms(i) Then
randoms(i) = Int(312 * Rnd)
blnFlag = False
Exit For
End If
blnFlag = True
Next
Loop