I have a function that randomly selects a picture from a table and display it. In the simulator the sample code below works perfectly, when I send it to device, only the first element from the table is selected. Any ideas? I can share the full app code if someone is interested in to take a look.
local temp = {"alex","john","josh"}
local tempNum = #temp
local function selectRandom(tName)
if (tName=="Random" or tName=="" or tName==nil) then
local randTemp = math.random(tempNum)
tempName = temp[randTemp]
local img=display.newImage(tempName..".jpg")
end
end
selectRandom()
I do this at the beginning of my app
math.randomseed(os.time())
dummy = math.random(0,255)
this takes care that the random numbers are always different.
why do I have to use math.randomseed? considering my other languages experience, all I should do was to use the random function... I will try. thanks!
generally a random number generator take a certain time value into account. With Lua/Corona it is when an app starts the apps runtime. So you will usually get always the same numbers. I think I seen this behaviour with other programming languages too.
The simulator is working great with the seed (every time i run it it comes with another data) but, when I move it to the device, the same image appears all the time.
Any ideas on what I could do here?
Not without seeing the code for a working example of the problem.
Did you seed the random generator at the start of your app like I showed you? Plus that dummy call of math.random?
Here goes:
math.randomseed = ( os.time() )
local tNum = 150
local places = {"place1", "place2", "placeN"}
-- Select a place randomically
local function selectRandom(tName)
if (tName=="Random" or tName=="" or tName==nil) then
--pick a random place, otherwise get the tName informed
randT = math.random(tNum)
randT = math.random(tNum)
tFile = places[randT]
else
tFile = tName
end
end
--Pick a temple to display
local randT = 0
randT = math.random(tNum)
selectRandom()
So no dummy call. There is a topic here on the forum, that the the first math.random call is always the same. That is why I posted about the dummy call.
I just verified that the dummy call IS needed or your random number always starts out the same. I tested this in the Corona SDK 1.1 simulator.
I went to the Lua.org demo site, http://www.lua.org/cgi-bin/demo, and entered the same code and it worked without the dummy call. I thought the Corona build was based on Lua 5.1 so I'm not sure why the Corona build fails to work correctly.
Tom
Here is the code. With the second line commented out, it shows the same number every time in the Simulator/terminal (99).
1 2 3 4 | math.randomseed(os.time()) --dummy = math.random(0,255) a = math.random(150) print(a) |
Tom
Seen while digging the random "problem" on mac osx:
"Lua's random uses C's rand and srand functions. The C90 standard defines the precise implementation of rand and srand, and this algorithm isn't the best. It especially lacks randomness in the lower bits. Some platforms like Linux changed the implementation of rand to an intentionally non-conforming, and better, implementation (e.g. random(3)). OS/X remains true to the standard rand implementation, and Lua inherits it."
I ran into the "problem" too. The simulator on lua.org executes the code you type on a linux machine, hence bypassing our osx platform behavior.
"Lua on mac osx converts the integer returned by rand() into a real number, effectively preserving only the high bits in the result. When you call math.random(1,100) from Lua on mac osx, the low-bit difference vanishes and you see the same integer result."
Here is what I am using to bypass the "same number always" oddity (works ok but not the best):
1 2 3 4 5 6 7 8 9 10 11 | local _seed = os.time() local function getRandom(f,c) _seed = _seed + 1 math.randomseed(_seed) math.random() local a = math.random(f,c) _seed = _seed + a return (a) end --get a random integer between 1 and 10 print (getRandom(1,10)) |
Maybe Ansca would work on that ? Quite annoying, indeed :)
Hasufel,
There is absolutely no need to re-seed like that. It actually makes your random numbers *less* random. I posted about this in a different thread when we were discussing the original issue a while back, but here's the short version:
1) Rand is an algorithm. It generates pseudo random numbers based on the seed given it.
2) Each time you feed it a different seed, you restart the random algorithm itself, in effect, you are taking the first number in a random sequence each time you call your "getRandom" function. This is not how the algorithm is intended to work and by doing it this way you actually make things less random.
3) The workaround is exactly as Mike posted. You seed once at the start of your app (with os.time()), then you immediately follow that with a dummy call to math.random(). From that point forward, you will get the correct random numbers.
The only time you should want to "re-seed" is if you are wanting to run the same sequence. This is often desirable to reproduce the same path previously. For instance, if you had a game where the setup was based on random numbers (like a sudoko or something), if you save the seed you use to create the board, then you can regenerate that board again just by setting the seed to the same number. The only gotcha is if you change any of the code so you don't utilize the random numbers in the same way.
At any rate, the point is, don't re-seed, that's a bad practice and totally unnecessary. Seed once, make a dummy math.random call, and you're good to go.
Scott
Thanks Scott for helping out.
I knew my trick was awful: I found it odd.
It works like a charm as Mike posted.
My bad !
Thank you :)
No problem. This oddity about math.random should be mentioned inside the App Programming Guide in big bold letters :-)
My friends, fact is, no matter I call the dummy or not (and I am calling), first number in the device is always the same. do you have any tested code showing how to get a new number in the device?
thanks!
1 2 3 4 5 6 | math.randomseed(os.time()); math.random(); for i = 1, 10 do print(i..") "..math.random()); end |
Every time I reload I get different numbers for all 10.
Simple tests like this put at the top of your main.lua can easily show you if you are making a mistake in your code or if it's an issue with lua.
Scott
Just tried your code. When you replace your code limiting the numbers in the random function, you will always get 1 as first number:
math.randomseed(os.time());
math.random(10); --considering the final table will have 10 elements
for i = 1, 10 do
print(i..") "..math.random(i));
end
Trying not to smile too much. :)
That's not how random works.
From lua.org Reference document:
----
math.random ([m [, n]])
This function is an interface to the simple pseudo-random generator function rand provided by ANSI C. (No guarantees can be given for its statistical properties.)
When called without arguments, returns a uniform pseudo-random real number in the range [0,1). When called with an integer number m, math.random returns a uniform pseudo-random integer in the range [1, m]. When called with two integer numbers m and n, math.random returns a uniform pseudo-random integer in the range [m, n].
----
First off, the dummy call is a dummy call. No need to pass anything to it.
Second, here's the loop you ran through:
Loop 1: Give me a random number between 1 and 1.
Loop 2: Give me a random number between 1 and 2.
Loop 3: Give me a random number between 1 and 3.
Loop 4: Give me a random number between 1 and 4.
Loop 5: Give me a random number between 1 and 5.
Loop 6: Give me a random number between 1 and 6.
Loop 7: Give me a random number between 1 and 7.
Loop 8: Give me a random number between 1 and 8.
Loop 9: Give me a random number between 1 and 9.
Loop 10: Give me a random number between 1 and 10.
Take the "i" out of the math.random call and replace it with the range you want. It sounds like you want a number between 1 and 10, so that would be math.random(10).
Scott
Scott my friend, this thing is driving me crazy!
I am doing exactly what you are suggested but my list in the device comes always the same.
math.randomseed = ( os.time() )
math.random()
myList = { "alex.jpg","eric.jpg","marina.jpg"}
function selectRandom()
local rand=math.random(#myList)
local tFile = myList[rand]
local background = display.newImage(tFile, 0, 0)
table.remove(myList,rand)
end
selectRandom()
everything works fine in the simulator but, when I run it in the device for the first time, it keeps showing the same list. For example, if the first time it built the random list as {1,2,1}, meaning {alex, marina, eric}, if i leave the app and run it again, "alex" will appear first, then "marina", then "Eric" - it never refresh the random list.
Alex
Well, there's a syntax error in the code you put here, but here's what I ran... it differs only in that it displays a text string instead of your image:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | math.randomseed(os.time()); math.random(); myList = { "alex.jpg", "eric.jpg", "marina.jpg", }; textY = 20; function selectRandom() local rand = math.random(#myList); local tFile = myList[rand]; local nt = display.newText(tFile, 20, textY, nil, 12); textY = textY + 20; nt:setTextColor(255, 255, 255); table.remove(myList, rand); end selectRandom(); selectRandom(); selectRandom(); |
You must remember, this is a very small sample of images. Your chances are 1 in 3 of always getting 1. That never changes no matter how many times you run this app. You always have a 33% chance to get 1 as you first number.
I did want to complement you on your method for not getting a recurring image. :)
At any rate, the code works. You will get different starting numbers. But you'll also get repeats.
Yes, the results were from running it on my iPhone as well as on the simulator.
Scott
Scott,
1) thanks for spending time here trying to help me;
2) i couldn't find the sintax error in the code I posted, as you mentioned. what have i missed?
3) my original table has more than 130 images. even with 130 elements in the table, the same list returns all the time;
5) to avoid this problem (which seems unsolved to me), I move my data to SQLite (thanks Asca for that!) and I am getting the Random() directly from SQL. Problem now is the code works perfect in the simulator but in the device, it is only returning the first record. Am I paying my sins with random functions? :)
I will try to solve both scenarios again.
Lastly, how can you format your code in these forums?
Thanks again,
Alex
No problem, Alex. I've no problem helping folks who are honestly giving it a good try before just coming here and asking for folks to write it for them. :)
1 | math.randomseed = ( os.time() ) |
Should be:
1 | math.randomseed( os.time() ) |
You use <code> and </code> around your code block.
If you really do have the above error in your code, then it could be the culprit.
With a sample set of 130 elements, something else is wrong.
Did you run my code above? If I had to guess, you've got a logic error somewhere in how you're getting your random element.
Bottom line, if you take the code I posted previously and run it (simulator and on your iphone) you'll see the random functionality working. With only 3 elements you *do* get the same list sometimes, but if you run it 5-10 times you'll see you get different lists.
Just like if you take the code I posted previously which generates 10 random numbers you'll see that works exactly as it's supposed to.
I advise you take the code posted here and try it out in a separate project, then go back and look at your code again and figure out what you're doing wrong.
Scott
do you seed the random number generator somewhere at first?