简体   繁体   English

Javascript:从随机集合中排除元素-(好奇心)

[英]Javascript : Exclude an element from a random set - (curiosity)

I have a question regarding javascript Math.random() : 我对javascript Math.random()有疑问:

I have (for a game I'm building) to randomly generate every number from a given set (ie from 0 to 1000) and every time I have to generate a number, I have to check if that number has already been "generated". 我(对于我正在开发的游戏)必须从给定的集合中随机生成每个数字(即从0到1000),并且每次必须生成一个数字时,我都必须检查该数字是否已经“生成”了。

The solution is pretty easy thinking about a simple algorithm that checks if the random integer is already present in the generated set. 该解决方案很容易想到一种简单的算法,该算法可以检查生成的集合中是否已经存在随机整数。 It loops generating numbers until it can't find it. 它循环生成数字,直到找不到为止。 A snippet below: 下面的代码段:

/* ... */
for(var i = 0; i<upperBound; i++){
    var randN = Math.floor(Math.random()*upperBound);
    while(myRandomNumbers.contains(randN)){
        loops++;
        randN = Math.floor(Math.random()*upperBound);
    }
    myRandomNumbers.push(randN);
}
/* ... */

running example here 在这里运行示例

I'd like to know: is this the best way to achieve this? 我想知道:这是实现这一目标的最佳方法吗? or are there any ways, instead of looping until it generates a "good" number, to exclude a particular set in the random generation? 还是有什么方法可以在随机生成中排除特定集合,而不是循环直到生成“好”数?

Thanks a lot everyone! 非常感谢大家!

  1. Generate the set of numbers in order. 按顺序生成一组数字。
  2. Sort the list randomly. 随机排序列表。

Here's an example using a naive, biased sort : 这是一个使用朴素的,有偏见的排序的示例:

for (var nums=[],i=0;i<1000;++i) nums[i]=i+1;
nums.sort(function(){ return Math.random()-0.5 });

Then you can just pop() numbers off of nums to get the next 'random' number, guaranteed to never have been used before. 然后,你可以pop()号断nums获得下一个“随机”数,保证从未被使用过。

If your range of number is not prohibitively large, you could simply generate a list with all the numbers, randomise it, then pick it off one by one. 如果您的数字范围不是很大,您可以简单地生成一个包含所有数字的列表,将其随机化,然后一一摘除。

Here's a quick hack of your sample implementation to show this method in action: http://www.jsfiddle.net/ZTLt9/8/ 这是您的示例实现的简要介绍,以演示此方法的实际作用: http : //www.jsfiddle.net/ZTLt9/8/

I'd create an array and randomly shuffle it: 我将创建一个数组并随机将其洗牌:

function shuffle(arr) {
    var shuffled = arr.slice(0), i = arr.length, temp, index;
    while (i--) {
        index = Math.floor(i * Math.random());
        temp = shuffled[index];
        shuffled[index] = shuffled[i];
        shuffled[i] = temp;
    }
    return shuffled;
}

// Create the array
var i = 1000, arr = [];
while (i--) arr[i] = i;

// Shuffle it
arr = shuffle(arr);

What about an array of booleans 1001 big. 布尔值1001大的数组呢?

When you want to check of the number has been generated, all you need to do is check the number at that position in the array: 当您要检查是否已生成数字时,只需检查数组中该位置的数字即可:

if (!arr[randomnumber]){
    arr[randomnumber] = true;
}

At the end, you can scan the array to find the numbers you need. 最后,您可以扫描阵列以找到所需的编号。

This has the added side effect of sorting your numbers, as the scan will pick them out in order. 这会给您的数字排序带来额外的副作用,因为扫描会按顺序将它们挑选出来。

Something similar to this was the subject of one of my blog posts: http://www.jameswiseman.com/blog/2010/05/27/generate-and-sort-lottery-numbers/ 与此类似的是我的一篇博客文章的主题: http : //www.jameswiseman.com/blog/2010/05/27/generate-and-sort-lottery-numbers/

The best way would probably be to generate an array of numbers, then shuffle it using the Fisher-Yates shuffle . 最好的方法可能是生成一个数字数组,然后使用Fisher-Yates shuffle对其进行洗牌

Here is the JavaScript example given in the Wikipedia article: 这是Wikipedia文章中给出的JavaScript示例:

var n = a.length;
for(var i = n - 1; i > 0; i--) {
    var j = Math.floor(Math.random() * (i + 1));
    var tmp = a[i];
    a[i] = a[j];
    a[j] = tmp;
}

(This assumes you have an array 'a' that contains the items you wish to shuffle.) (这假设您有一个数组“ a”,其中包含您要洗牌的项目。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM