简体   繁体   English

如何制作没有重复的随机数组?

[英]How can I make a random array with no repeats?

I've been searching around for some answers to this issue, but nothing seems to work when I try to find a solution. 我一直在寻找这个问题的一些答案,但是当我试图找到解决方案时似乎没有任何效果。

What I'm trying to achieve is to make a spinner in Javascript & Adobe Edge that randomly spins on a number , and does not repeat that number again until all numbers have been spinned. 我想要实现的是在Javascript和Adobe Edge中创建一个随机旋转数字的微调器,并且所有数字都被旋转之前不再重复该数字

I know this should be fairly easy to do for a decent coder, but I'm not that experienced yet. 我知道对于一个体面的程序员来说这应该是相当容易的,但我还不是那么有经验。

This is what I have so far, but it is unfinished and buggy: 这是我到目前为止所做的,但它是未完成的和错误的:

var myArray = ['360', '330', '300', '270', '240', '210', '180', '150', '120', '90', '60', '30'];
var Spinner1 = sym.$('Spinner1');

Spinner1.click(function(){
// randomize the degree of spin.
var mySpin = myArray[Math.floor(Math.random() * myArray.length)];

sym.getSymbol('Spinner1').play();
        Spinner1.css({
                    '-webkit-transform': 'rotate(' + mySpin + 'deg)',
                    '-moz-transform': 'rotate(' + mySpin + 'deg)',
                    '-ms-transform': 'rotate(' + mySpin + 'deg)',
                    '-o-transform': 'rotate(' + mySpin + 'deg)',
                    'transform': 'rotate(' + mySpin + 'deg)',
   });
   Spinner1.css('-webkit-transition','all 500ms cubic-bezier(0.420, 0.000, 1.000, 1.000)');

   if (mySpin > 300 && mySpin < 360) {
   alert("Winner is number 1!");
   }
});

Hope someone could help me out. 希望有人可以帮助我。 Thanks in advance. 提前致谢。

There are two ways you could achieve this. 有两种方法可以实现这一目标。

  1. Store an array of values already spun. 存储已旋转的值数组。 Then, when you generate a new number, check if it's in the array of spun numbers. 然后,当您生成一个新数字时,检查它是否在旋转数字数组中。 If it is, generate a new number and check again, until you get a number which isn't in the array. 如果是,则生成一个新数字并再次检查,直到得到一个不在数组中的数字。 Otherwise, add it to the array. 否则,将其添加到阵列。

  2. Generate an array of all the valid numbers up front, as you are doing. 正如您所做的那样,预先生成所有有效数字的数组。 Then, every time you spin a number, remove it from that array. 然后,每次旋转数字时,将其从该数组中删除。 That way, the next time you 'spin' you will be only selecting from values which haven't been spun already. 这样,下次你“旋转”时,你将只选择尚未旋转的值。

  3. Generate an array of all the valid numbers up front, and then sort it randomly. 预先生成所有有效数字的数组,然后随机排序。 Then all you have to do is keep taking the first item in the array. 然后,您所要做的就是继续获取​​数组中的第一项。

In order, Option 3. is the most elegant, but it has the downside that someone with a console open could potentially see exactly what number is coming next! 顺便提一下,选项3是最优雅的,但它有一个缺点,即打开控制台的人可能会看到下一个确切的数字! Option 2 is the next best, and if the user is allowed to know that a number can't come up twice, they can't 'cheat' by seeing the remaining available numbers. 选项2是次佳的,如果允许用户知道某个号码不能出现两次,他们就不能通过查看剩余的可用号码来“欺骗”。 Option 1 is the least efficient - because it means your code will need to do more and more work to try and find a 'free' number. 选项1效率最低 - 因为这意味着您的代码需要做越来越多的工作来尝试找到“免费”号码。

Honestly, if your game needs to be at all secure from hacking, then you would not want to generate any random numbers client side anyway, so if this is just for a bit of fun, it won't really matter which method you use. 老实说,如果你的游戏需要完全不受黑客攻击,那么你不会想要生成任何随机数的客户端,所以如果这只是为了一点乐趣,那么你使用哪种方法并不重要。 If you are writing it for a gambling website, first let me know which one so I can make a fortune, and then move your logic to the server. 如果你是为赌博网站写的,首先让我知道哪一个我可以发财,然后将你的逻辑移到服务器上。

So here is an example of Option 2. approach 所以这是选项2方法的一个例子

<!DOCTYPE html>
<html>
<head>
    <script>

        var numbers = []; // this array will store the available numbers..

        function generateNumbers()
        {
            // populate the available numbers however you need to..
            for(var i=0; i<360; i+=30)
            {
                numbers.push(i);
            }
        }

        function spin()
        {
            if(numbers.length==0)
            {
                // then we've used  up all available numbers..start new game or whatever you need to do..
                alert("starting again");
                generateNumbers();
            }
            var rand = Math.floor(Math.random()*numbers.length); // select an index randomly based on the number of remaining available numbers..
            var num = numbers[rand];
            numbers.splice(rand,1); // remove the number we selected so it can't be selected next time..
            document.getElementById("number").innerHTML = num;
        }

    </script>
</head>
<body>
<button onclick="spin()">SPIN</button>
<div id="number"></div>
</body>
</html>

And Option 3. below. 以及选项3.下面。 The main difference is that you can just shift() the next value instead of having to select randomly. 主要区别在于您只需移动()下一个值而不必随意选择。

<!DOCTYPE html>
<html>
<head>
    <script>

        var numbers = [];

        function generateNumbers()
        {
            for(var i=0; i<360; i+=30)
            {
                numbers.push(i);
            }
            function sort(a,b)
            {
                return (Math.random()>0.5)? -1 : 1;
            }
            numbers.sort(sort);
        }

        function spin()
        {
            if(numbers.length==0)
            {
                alert("starting again");
                generateNumbers();
            }
            var num = numbers.shift();
            document.getElementById("available").innerHTML = "Available:" + numbers.join(",");
            document.getElementById("number").innerHTML = "Selected:" + num;
        }

    </script>
</head>
<body>
<button onclick="spin()">SPIN</button>
<div id="available"></div>
<div id="number"></div>
</body>
</html>

Hopefully that gives you an idea of how you could incorporate this into your code. 希望这能让您了解如何将其合并到您的代码中。

It looks like you already have an array of the possible values. 看起来你已经有了一系列可能的值。 In this case you can simply shuffle the array and go through it. 在这种情况下,您可以简单地对阵列进行洗牌并完成它。 JavaScript doesn't have a built in shuffle function, but its pretty simple to implement. JavaScript没有内置的shuffle函数,但实现起来非常简单。

Here is an example of a Fisher–Yates shuffle 这是Fisher-Yates shuffle的一个例子

function shuffle(array) {
  for(var i = array.length; i > 1; i--) {
    var r = Math.floor(Math.random() * i);
    var temp = array[r];
    array[r] = array[i-1];
    array[i-1] = temp;
  }
}

What you need to do in your case is, pick a random number and store it in an array , but before you store it, check if it already exists in that array , if it does, then pick another. 在你的情况下你需要做的是, 选择一个随机数并将其存储在一个数组中 ,但在存储它之前, 检查它是否已存在于该数组中 ,如果存在,则选择另一个。 And if your picked values array contains all the possible values, then reset the array. 如果您选择的值数组包含所有可能的值,则重置数组。

Here is the sample : https://jsfiddle.net/5a7mqsbn/1/ 以下是示例: https//jsfiddle.net/5a7mqsbn/1/

 var alreadyArr = new Array(); $(function() { $("#generate").click(function() { var newFound = false; do { var num = (Math.floor(Math.random() * 12) + 1) * 30; if (alreadyArr.length == 12) { alreadyArr = [num]; newFound = true; } else if (alreadyArr.indexOf(num) < 0) { alreadyArr.push(num); newFound = true; } } while (!newFound); $("#numbers").text(alreadyArr); }); }); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <p id="numbers"></p> <button id="generate"> Next Random number </button> 

    var array = [];

    setInterval(function(){

        if(array .length === 0){ 
            reload(); 
        }

        var result = getRandom();

        console.log(result);

    },1000);

    function getRandom(){
        var index = (array.length === 1 ? 0 : Math.floor(Math.random() * array.length));
        return array.splice(index, 1)[0];
    }

    function reload(){
        array = [2,3,4,5,6,7,8,9,0,1,44,66];
    }

This function will use Math.random() to randomly choose a number in an array, and not choosing it again until all numbers were used: 此函数将使用Math.random()随机选择数组中的数字,并且在使用所有数字之前不再选择它:

var originalArray = ['360', '330', '300', '270', '240', '210', 
'180', '150', '120', '90', '60', '30'];

var totalSpin = [];

function spinArray(){
    var spin = Math.floor(Math.random()*originalArray.length);
    if(totalSpin.indexOf(spin) == -1){
        totalSpin.push(spin);
        parag.innerHTML = originalArray[spin];
    } else { 
        spinArray(); 
    }
    if(totalSpin.length == originalArray.length)
          totalSpin = [];
}

Here is the fiddle: https://jsfiddle.net/628yqz0v/4/ 这是小提琴: https//jsfiddle.net/628yqz0v/4/

Another approach you could take given the fact that you already have the array values and you need to randomize their position is to generate a unique random values with Set : 鉴于您已经拥有数组值并且需要randomize其位置这一事实,您可以采取的另一种方法是使用Set生成unique random values

 var data = ['360', '330', '300', '270', '240', '210','180', '150', '120', '90', '60', '30']; let getUniqueRandomNumbers = n => { let set = new Set() while (set.size < n) set.add(Math.floor(Math.random() * n)) return Array.from(set) } let result = getUniqueRandomNumbers(data.length).map(x => data[x]) console.log(result) 

The idea is to generate the indexes of the new array and then using those to populate it via Array.map . 我们的想法是生成新数组的索引,然后使用它们通过Array.map填充它。

Another approach you could take is via Array.sort and Math.random : 您可以采用的另一种方法是通过Array.sortMath.random

 var data = ['360', '330', '300', '270', '240', '210','180', '150', '120', '90', '60', '30']; let result = data.sort(function(a, b){ return 0.5 - Math.random() // <— sort needs a number and this makes it work }); console.log(result); 

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

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