我需要得到随机数,但它不应该等于之前的数字.这是我的代码片段.但它不起作用.
function getNumber(){
var min = 0;
var max = 4;
var i;
i = Math.floor(Math.random() * (max - min)) + min;
if (i=== i) {
i = Math.floor(Math.random() * (max - min)) + min;
}
return i;
};
console.log(getNumber());
Run Code Online (Sandbox Code Playgroud)
Nin*_*olz 20
这个答案提出了三次尝试
一个简单的版本与功能的属性getNumber
,last
,其中存储最后随机值.
如果小于,则使用对min
和max
值的闭包的版本,引发异常.max
min
一个版本,结合了闭包和保持所有随机值的想法,并在合适的时候使用它.
一
您可以使用属性getNumber
来存储最后一个数字并使用do ... while
循环.
function getNumber() {
var min = 0,
max = 4,
random;
do {
random = Math.floor(Math.random() * (max - min)) + min;
} while (random === getNumber.last);
getNumber.last = random;
return random;
};
var i;
for (i = 0; i < 100; i++) {
console.log(getNumber());
}
Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper { max-height: 100% !important; top: 0; }
Run Code Online (Sandbox Code Playgroud)
二
关于间隔和最后一个随机值的闭包的另一个提议.
function setRandomInterval(min, max) {
var last;
if (min >= max) {
throw 'Selected interval [' + min + ', ' + max + ') does not work for random numbers.';
}
return function () {
var random;
do {
random = Math.floor(Math.random() * (max - min)) + min;
} while (random === last);
last = random;
return random;
};
}
var i,
getRandom = setRandomInterval(0, 4);
for (i = 0; i < 100; i++) {
console.log(getRandom());
}
setRandomInterval(4, 4); // throw error
Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper { max-height: 100% !important; top: 0; }
Run Code Online (Sandbox Code Playgroud)
三
该提议使用该想法来最小化新随机数的调用.它适用于两个变量,value
用于连续相同的随机值和count
用于保存相同值的计数.
如果给出了保存的计数,并且该值与最后一个值不相等,则该函数首先查找.如果发生这种情况,则返回保存的值并减少计数.
否则,如上所述生成并检查新的随机数(第一提议).如果该数字等于最后一个值,则计数递增并继续生成新的随机值.
结果,几乎所有先前生成的随机值都被使用.
function setRandomInterval(min, max) {
var last, // keeping the last random value
value, // value which is repeated selected
count = 0, // count of repeated value
getR = function () { return Math.floor(Math.random() * (max - min)) + min; };
if (min >= max) {
throw 'Selected interval [' + min + ', ' + max + ') does not work for random numbers.';
}
return function () {
var random;
if (count && value !== last) {
--count;
return last = value;
}
random = getR();
while (random === last) {
value = random;
++count;
random = getR();
}
return last = random;
};
}
var i,
getRandom = setRandomInterval(0, 4);
for (i = 0; i < 100; i++) {
console.log(getRandom());
}
Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper { max-height: 100% !important; top: 0; }
Run Code Online (Sandbox Code Playgroud)
Con*_*Fan 15
以下方法在[min,max]范围内生成一个新的随机数,并确保此数字与前一个不同,没有循环且没有递归调用(Math.random()
仅调用一次):
为了将先前的数字保留在闭包中,getNumber
可以在IIFE中创建:
// getNumber generates a different random number in the inclusive range [0, 4]
var getNumber = (function() {
var previous = NaN;
return function() {
var min = 0;
var max = 4 + (!isNaN(previous) ? -1 : 0);
var value = Math.floor(Math.random() * (max - min + 1)) + min;
if (value >= previous) {
value += 1;
}
previous = value;
return value;
};
})();
// Test: generate 100 numbers
for (var i = 0; i < 100; i++) {
console.log(getNumber());
}
Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper {
max-height: 100% !important;
top: 0;
}
Run Code Online (Sandbox Code Playgroud)
通过在以下语句中添加1来使[min,max]范围包含在内max - min
:
var value = Math.floor(Math.random() * (max - min + 1)) + min;
Run Code Online (Sandbox Code Playgroud)
这不是问题的要求,但使用包容性范围对我来说更自然.
这个帖子中的大部分答案都过于复杂.
这是一个简洁的例子,说明我将如何做到这一点:
function getNumber(){
return (getNumber.number = Math.floor(Math.random() * (4 + 1))) === getNumber.lastNumber ? getNumber() : getNumber.lastNumber = getNumber.number;
}
console.log(getNumber()); // Generates a random number between 0 and 4
Run Code Online (Sandbox Code Playgroud)
实例:https://jsfiddle.net/menv0tur/3/
首先,函数应该与之前的值进行比较,现在我们只有i
与自身进行比较的变量.为了确保我们没有先前的值,我们需要在内部进行循环(在我的解决方案中递归),因为单个if statement
不能确保第二个随机数不相同(存在机会).您的数字设置非常小,因此碰撞的可能性很高,循环可能需要很少的执行.
function getNumber(prev){
var min = 0;
var max = 4;
var next;
next = Math.floor(Math.random() * (max - min)) + min;
if (next===prev) {
console.log("--run recursion. Our next is ="+next); //log only for test case
next = getNumber(prev); //recursive
}
return next;
};
//test 100 times
var num=0;
for ( var i=0; i<100; i++){
num=getNumber(num);
console.log(num);
}
Run Code Online (Sandbox Code Playgroud)
正如您在测试中看到的那样,我们永远不会有两个相同的值彼此相邻.我还添加了一些console.log
来显示需要运行多少次递归才能找到与前一个不同的下一个数字.
跟踪最后生成的数字。生成新号码时,请检查它是否与上一个不同。如果不是,请继续生成新的数字,直到它不同为止,然后输出它。
var getNumber = (function(){
var min = 0;
var max = 4;
var last = -1;
return function(){
var current;
do{
// draw a random number from the range [min, max]
current = Math.floor(Math.random() * (max + 1 - min)) + min;
} while(current === last)
return (last = current);
}
})();
// generate a sequence of 100 numbers,
// see that they all differ from the last
for(var test = [], i = 0; i < 100; i++){
test[i] = getNumber();
}
console.log(test);
Run Code Online (Sandbox Code Playgroud)
如评论和其他答案中所述,上述方法的潜在缺点是,如果生成的数字等于前一个数字,则可能需要进行几次尝试以生成随机数。请注意,需要进行多次尝试的可能性非常低(遵循快速下降的几何分布)。出于实际目的,这不太可能产生明显的影响。
但是,可以通过从范围[min,max]中的数字集中直接绘制一个随机数来排除新的随机数,而先前尝试绘制的数字除外:这在@答案中得到了很好的证明ConnorsFan,每个函数调用仅生成一个随机数,而随机性仍然保留。
您需要一个比函数本地变量具有更大作用域的变量getNumber
。尝试:
var j;
function getNumber(){
var min = 0;
var max = 4;
var i = Math.floor(Math.random() * (max - min)) + min;
if (j === i) {
i = getNumber();
}
j = i;
return i;
};
Run Code Online (Sandbox Code Playgroud)