How can I make a random array with no repeats?

£可爱£侵袭症+ 提交于 2019-11-29 16:16:30

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! 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. 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.

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

<!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. 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.

Here is an example of a 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/

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:

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/

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:

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.

Another approach you could take is via Array.sort and Math.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);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!