I. Background to the issue
A two-dimensional plane has a group of NPCs, each turn can be randomly up/down/left/right in either direction 1 steps, there is Unit collision Volume (NPC position can not coincide)
The rule is so simple that initially the NPC is artificially distributed evenly on a two-dimensional plane, and after running n rounds, it is found that all NPCs are concentrated in the lower left corner. How could this be, a good deal of random?
Two. Analysis
The existing implementation is this:
Based on the current position of the NPC to determine where to go, the result is stored in the one-dimensional array arr
P.S. Up/down/left/right up to 4 points (around empty), at least 0 points (enclosed)
Generates a random number within [0, arr.length–1] as the target location index value
Generate random number [min, Max]w.util.rand = function (min, max) { return Math.Round (Math.random () * (max-min) + min);}
Controlling the location of NPC moves to Arr[index]
Logic should be no problem, but why is the NPC running to the lower left corner of the meeting? Wait, why is it lower left instead of the other corner?
Because the first step to achieve the time is in accordance with the left-to-right order, and finally went to the lower left corner, indicating that the probability of upward and right is too small (generating a random number of functions Rand is not a problem, and can actually get [min, max] number)
The root cause of the problem is that math.random () does not give a force, generating a decimal between [0, 1), taking 0 and a value close to 1 is very small, so the random number generated by the rand () function is less likely to take min and mix, and the likelihood of upward/right is small.
Three. Solution
Since the probability of taking the Min and Max is very small, the median probability is more uniform, then good to do, cut off these two values just fine. The specific implementation is as follows:
function Randex (min, max) { var num; var maxex = max + 2; Extend the range to [min, Max + 2], introduce two extra values to replace Min/max do{ num = Math.Round (Math.random () * (maxex-min) + min) ; num--; } while (num < min | | num > MAX); The range is not correct, continue to loop return num;}
It is worth mentioning that the above plus 2 minus 1 is clever enough to exclude Min and Max
Four. Running results
The probability difference of the math.random () return value in JS may be larger than you think, which is unacceptable in practical applications.
The test code is as follows:
Generate random number [min, Max]w.util.rand = function (min, max) {return Math.Round (Math.random () * (max-min) + min);} Generate more random random numbers [min, max]function randex (min, max) {var num; var maxex = max + 2; Extend the range to [min, Max + 2], introduce two extra values to replace Min/max do{num = Math.Round (Math.random () * (maxex-min) + min); num--; } while (num < min | | num > MAX); The range is not correct, continue to loop return num;} function Testrand (times, fun) {var arr = [1, 2, 3, 4]; var count = []; var randval; for (var i = 0; I < times; i++) {//Get [0, 3] random number Randval = Fun (0, arr.length-1); Record Count if (typeof Count[randval]!== "number") {Count[randval] = 0; } count[randval]++; } console.log (count);} Console.log ("The Times"); Testrand (W.util.rand); Prior implementation of Testrand (RANDEX); Improved implementation of Console.log ("The Times"); Testrand (W.util.rand); Previous implementations of Testrand (Randex); Improved implementation Console.log ("10000 times"); Testrand (10000, W.util.rand); Previous implementations of Testrand (10000, randex); Improved implementation of Console.log ("100000 times"); Testrand (100000, W.util.rand); Previous implementations of Testrand (100000, randex); Improved implementations
The results of the operation are as follows:
See, the effect is still very good
Something
In theory Java math.random (), C # 's next may also exist this problem, there is no need to verify, because the idea of randex function (plus 2 minus 1, too bad effect can add 4 minus 2, plus 6 minus 3 ...) Until satisfied) is universal
JS more random random number