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
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;
}
}
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/
There are two ways you could achieve this.
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.
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.
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.
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>
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);