Agent Zebra Agent Zebra - 3 months ago 9
Javascript Question

How to generate a new random number (that's different from the previous random number)

I'm trying to change the following (that currently returns a random number from an array), so that each random number is different from the last one chosen.

function randomize(arr) {
return arr[Math.floor(Math.random()*arr.length)];
}

oracleImg = [];
for (var i=1;i<=6;i++) {
oracleImg.push(i);
}

randOracleImg = randomize(oracleImg);


I tried the following, but it's not always giving me a number different from the last number.

function randomize(arr) {
var arr = Math.floor(Math.random()*arr.length);
if(arr == this.lastSelected) {
randomize();
}
else {
this.lastSelected = arr;
return arr;
}
}


How can I fix this?

Answer

Your existing function's recursive randomize() call doesn't make sense because you don't pass it the arr argument and you don't do anything with its return value. That line should be:

return randomize(arr);

...except that by the time it gets to that line you have reassigned arr so that it no longer refers to the original array. Using an additional variable as in the following version should work.

Note that I've also added a test to make sure that if the array has only one element we return that item immediately because in that case it's not possible to select a different item each time. (The function returns undefined if the array is empty.)

function randomize(arr) {
    if (arr.length < 2) return arr[0];
    var num = Math.floor(Math.random()*arr.length);
    if(num == this.lastSelected) {
        return randomize(arr);
    } else {
        this.lastSelected = num;
        return arr[num];
    }
}

document.querySelector("button").addEventListener("click", function() {
    console.log(randomize(["a","b","c","d"]));
});
<button>Test</button>

Note that your original function seemed to be returning a random array index, but the code shown in my answer returns a random array element.

Note also that the way you are calling your function means that within the function this is window - not sure if that's what you intended; it works, but basically lastSelected is a global variable.

Given that I'm not keen on creating global variables needlessly, here's an alternative implementation with no global variables, and without recursion because in my opinion a simple while loop is a more semantic way to implement the concept of "keep trying until x happens":

var randomize = function () {
    var lastSelected, num;
    return function randomize(arr) {
        if (arr.length < 2) return arr[0];
        while (lastSelected === (num = Math.floor(Math.random()*arr.length)));
        lastSelected = num;
        return arr[num];
    };
}();

document.querySelector("button").addEventListener("click", function() {
    console.log(randomize(["a","b","c","d"]));
});
<button>Test</button>