http://koreanwordgame.com/
This page first loads 4 words into the options DIVs via Ajax and then randomizes the correct answer with the following function, passing the DIV containing the elements to be randomized as the argument:
var random = function(r){
r.children().sort(function(a,b){
var temp = parseInt( Math.random()*10 );
return( temp%2 );
}).appendTo(r);
};
random($("#option"));
<div id="option">
<div class="option" id="option1" style="background-color: rgb(229, 232, 238); ">light</div>
<div class="option" id="option4" style="background-color: rgb(183, 190, 204); ">pot</div>
<div class="option" id="option2" style="background-color: rgb(183, 190, 204); ">garlic press</div>
<div class="option" id="option3" style="background-color: rgb(183, 190, 204); ">habitant</div>
</div>
The problem is that in Safari the correct answer is always in the top position...
And in IE 7 and 8 it's in the top position far more often than not.
I know it would be possible to make the function "more random" by using a timestamp in there or something but I'm struggling to make it work properly.
The problem isn't Math.random()
. It's your "randomizing" sort function, which only ever returns 0
or 1
, and never -1
. Here's how to properly generate a random int in the interval [-1. 1]
, based on MDC's getRandomInt
function:
Math.floor(Math.random() * 3) - 1;
(simplified from getRandomInt(-1, 1)
).
That said, as @32bitkid commented, the right way is to use a Fischer-Yates shuffle.
Part of the problem you're having is how you're using the random function. The sort function takes another function that is used to compare any two elements in the list. One of the assumptions made by the sort function is that the results of the comparison between any two elements is both stable and consistent (i.e., if a < b and b < c, then a < c), and you're function violates that assumption. So, there's really no guarantees as to what the sort function will do in this case. Depending upon how the sort function is implemented (I don't know which algorithm is used in javascript off hand), you will most likely not get a truely random order where each item is equally likely to appear in any given position.
The simplest solution I can think of is to generate a random number for each item you want to sort, and then sort the items by that randomly generated number. This is different from your approach in that comparing any two elements in your list will always produce the same result while the items are being sorted.
return( temp%2 );
Leaves you with only 0
or 1
Try using return( temp%4 );
Which would leave you with 0
,1
,2
,3
Although I am not sure what the modulus is for.
This will get you a random number between 0 and 3:
Math.floor(Math.random()*4)
So all you need to do is:
var random = function(r){
r.children().sort(function(a,b){
return Math.floor(Math.random()*4);
}).appendTo(r);
};