我正在尝试更改以下内容(当前从数组中返回一个随机数),以便每个随机数与上一个随机数不同。
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);
我尝试了以下内容,但并不总是给我一个与上一个数字不同的数字。
function randomize(arr) {
var arr = Math.floor(Math.random()*arr.length);
if(arr == this.lastSelected) {
randomize();
}
else {
this.lastSelected = arr;
return arr;
}
}
我该如何解决这个问题?
答案 0 :(得分:1)
您现有的函数的递归randomize()
调用没有意义,因为您没有通过arr
论证,而且您没有做任何事情它的回报价值。该行应该是:
return randomize(arr);
...除了当它到达该行时,您已重新分配arr
,以便它不再引用原始数组。使用以下版本中的附加变量应该有效。
请注意,我还添加了一项测试,以确保如果数组只有一个元素,我们会立即返回该项,因为在这种情况下,每次都无法选择不同的项目。 (如果数组为空,则函数返回undefined
。)
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"]));
});
&#13;
<button>Test</button>
&#13;
请注意,您的原始函数似乎返回了一个随机数组 index ,但我的答案中显示的代码返回一个随机数组元素。
另请注意,您调用函数的方式意味着在函数this
中是窗口 - 不确定这是否符合您的意图;它有效,但基本上lastSelected
是一个全局变量。
鉴于我并不热衷于不必要地创建全局变量,这里是一个没有全局变量的替代实现,没有递归,因为在我看来,一个简单的while循环是一种更加语义的方式来实现&#34;继续尝试直到 x 发生&#34;:
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"]));
});
&#13;
<button>Test</button>
&#13;
答案 1 :(得分:1)
下面的代码只是一个例子,它将生成99个数字,所有都将是唯一的和随机的(范围是0-1000),逻辑很简单只需在临时数组中添加随机数并比较新的随机数(如果它已经生成)或不。
var tempArray = [];
var i=0;
while (i != 99) {
var random = Math.floor((Math.random() * 999) + 0);
if (tempArray.indexOf(random)==-1) {
tempArray.push(random);
i++;
} else {
continue;
}
}
console.log(tempArray);
&#13;
答案 2 :(得分:1)
如果你想总是从一个数组中返回一个不同的数字,那么就不要随意改组,而是洗牌!*
最简单的公平(真正随机)混洗算法是Fisher-Yates算法。不要做同样的mistake Microsoft did and try to abuse .sort()
to implement a shuffle。只需实施Fisher-Yates (otherwise known as the Knuth shuffle):
// Fisher-Yates shuffle:
// Note: This function shuffles in-place, if you don't
// want the original array to change then pass a copy
// using [].slice()
function shuffle (theArray) {
var tmp;
for (var i=0; i<theArray.length;i++) {
// Generate random index into the array:
var j = Math.floor(Math.random()*theArray.length);
// Swap current item with random item:
tmp = theArray[i];
theArray[j] = theArray[i];
theArray[i] = tmp;
}
return theArray;
}
所以就这样做:
shuffledOracleImg = shuffle(oracleImg.slice());
var i=0;
randOracleImg = shuffledOracleImg[i++]; // just get the next image
// to get a random image
您希望如何处理图像耗尽取决于您。像iTunes这样的媒体播放器或iPhone,iPad和iPod上的音乐播放器让用户可以选择从一开始就停止播放或重复播放。一些纸牌游戏软件将重新洗牌并重新开始。
*注意:我的一个小小的烦恼是随机化而不是随机播放的音乐播放器软件。随机化是完全错误的事情,因为1.有些实现不会检查下一首歌是否与当前歌曲相同,因此你会播放两首歌曲(你似乎想要避免的)和2.歌曲最终永远不会被播放。从头到尾随机播放和播放洗牌播放列表可以避免这两个问题。 CD播放器制造商做对了。 MP3播放器开发者往往会弄错。
答案 3 :(得分:1)
这是一个版本,它将确保一个始终与最后一个不同的随机数。另外,您可以控制生成的随机值的最大值和最小值。默认值为max:100和min:1
var randomize = (function () {
var last;
return function randomize(min, max) {
max = typeof max != 'number' ? 100 : max;
min = typeof min != 'number' ? 1 : min;
var random = Math.floor(Math.random() * (max - min)) + min;
if (random == last) {
return randomize(min, max);
}
last = random;
return random;
};
})();