Generate 3 different random numbers without duplic

Get help using Construct 2

Post » Sun Mar 04, 2012 2:35 am

I want to generate three random numbers between 0 and 6, and pass them to global variables. this is what I have:

set one to floor(random(6))
set two to floor(random(6))
set three to floor(random(6))

I cant figure out how to make sure that none of these three numbers are the same.
B
2
Posts: 1
Reputation: 302

Post » Sun Mar 04, 2012 4:39 am

I know a method but not now to apply it to construct 2.

- Put the first value into an array,

- start a while loop that doesn't close until the size of the array matches the number of values you need.

- generate a random number...
- compare it to everything in the array...
- if it doesn't match anything, add it to the array...
B
10
S
5
G
1
Posts: 37
Reputation: 1,631

Post » Sun Mar 04, 2012 5:06 am

You can do the array method, but here's a lazier way:

http://dl.dropbox.com/u/19702035/randomstuff.capx

It works for a smaller amount of numbers, but if you wanna do more the array method works better. I'll show you how to do that too if you want.
B
20
S
9
G
6
Posts: 607
Reputation: 6,112

Post » Sun Mar 04, 2012 5:07 am

There's no while loop in c2.

The only sure way I know to do a sampling without replacement is to make a list of your sample, pick one at random, delete the sample from the list.

I showed an implementation not long ago.
It went a bit like that:
[code]global sampleCount = 3 // number of... number you want
+System: on start of layout
-> Array: set size to sampleCount,1,1
+On What you want
Local text list = "0,1,2,3,4,5,6"
+repeat sampleCount times
    -> Array: set value at loopindex to int((tokenat(list,floor(random(tokencount(list,","))),",")))
    -> System: set list to replace(list,str(Array.At(loopindex)),"")
    -> System: set list to replace(list,",,",",")
    -> System: set list to (left(list,0,1) = ",") ? right(list,len(list)-1) : list
    -> System: set list to (right(list,len(list-1),1) = ",") ? left(list,len(list)-1) : list[/code]


The four last actions are used to delete the token from the list string. This way you don't pick it again.
[code]    -> System: set list to replace(list,Array.At(loopindex),"")[/code]
Delete the token leaving the comas
1,2,3 -> ",2,3" or "1,,3" or "1,2,"

[code]    -> System: set list to replace(list,",,",",")[/code]
Check if there's two comas side to side and delete one
1,2,3 -> ",2,3" or "1,3" or "1,2,"

[code]    -> System: set list to (left(list,0,1) = ",") ? right(list,len(list)-1) : list[/code]
Check if the first character is a coma and delete it
1,2,3 -> "2,3" or "1,3" or "1,2,"

[code]    -> System: set list to (right(list,len(list-1),1) = ",") ? left(list,len(list)-1) : list[/code]
Check if last character is a coma and delete it
1,2,3 -> "2,3" or "1,3" or "1,2"
Yann2012-03-04 05:10:11
B
60
S
22
G
14
Posts: 1,479
Reputation: 16,346

Post » Sun Mar 04, 2012 5:08 am

... Aaaaand that's the not lazy way.
B
20
S
9
G
6
Posts: 607
Reputation: 6,112

Post » Sun Mar 04, 2012 5:22 am

@SullyTheStrange
You're way is ugly :D... But indeed pretty neat for the question asked

However I would add another global variable that goes from 0 to 1 once one!=two!=three
To tell the game "ok the variables are now good we can continue"

You made me realize there's indeed a while in c2... The gameloop itself (:Yann2012-03-04 05:23:32
B
60
S
22
G
14
Posts: 1,479
Reputation: 16,346

Post » Thu Mar 08, 2012 2:48 am

@Yann:
I'm not sure, but looking at your implementation, it looks like it would cause problems with sets that contained values which have substrings which match other values, eg:
1,2,3,4,5,6,7,8,9,10,11

ex: program picks 1
set list to replace(list,str(Array.At(loopindex)),"")

Replace will wipe out the '1' string in '1', '10', and '11'

A while back when I was working on a text-parser with C2, I encountered a similar problem and ended up having to manually traverse and remove without the replace expression.
B
30
S
6
G
8
Posts: 232
Reputation: 6,119

Post » Thu Mar 08, 2012 8:17 am

A way to handle that that I have used in the past is to use a leading and trailing comma in the list, then not use the first and last tokens, which would be "".

Here is Yann's example tweaked with that in mind.
[code]global sampleCount = 3 // number of... number you want
+System: on start of layout
-> Array: set size to sampleCount,1,1
+On What you want
Local text list = ",0,1,2,3,4,5,6,"
+repeat sampleCount times
    -> Array: set value at loopindex to int((tokenat(list,int(random(tokencount(list,",")-2)+1),",")))
    -> System: set list to replace(list , ","&str(Array.At(loopindex))&"," , ",")[/code]
B
79
S
24
G
54
Posts: 4,738
Reputation: 40,739

Post » Thu Mar 08, 2012 12:49 pm

@cacotigon
Yep you're super right and I felt into that kind of issue. I solved it by using zerofill numbers.
I think I used r0j0's way too once. Don't remember, I tend to reinvent the wheel sometimes :D

with zerofill you don't fall into the substring issue

"001,002,003,010,110,102,etc"
if you replace(str,"001","") you won't have any issue
and you can still int("003") into 3 with no problem.

But yeah... use r0j0's way... it's the cleanest (: Yann2012-03-08 12:50:30
B
60
S
22
G
14
Posts: 1,479
Reputation: 16,346

Post » Mon May 14, 2012 10:57 pm

This post has been super helpful in assisting me in understanding tokens and how to randomly pull from them. I am having one hang up with Yann's example. In the line
"System: set list to (left(list,0,1) = ",") ? right(list,len(list)-1) : list"
Construct is telling me that left can only have to parameters? What am I missing? been beating my head on this for a full day trying to understand. And Special thanks to Yann! always popping up in the forums I have searched with some intense tech responses.
B
6
S
2
G
2
Posts: 6
Reputation: 1,801

Next

Return to How do I....?

Who is online

Users browsing this forum: TELLES0808 and 18 guests