问题描述
我对编码非常陌生(大约 3 周前写了我的第一行 html),对于我自己的第一个项目,我想创建一个显示随机图像的小画廊。
首先,每次调用该函数时,我只能设法显示相同的图像,然后我设法使图像分别滚动,但可能会出现重复。最后,在一些帮助下,我得到了当前版本:
//Images array and global vars
let theImages = [];
for (let i = 0; i <= 25; i++) {
theImages[i] = "stevejohnson_" + i + ".jpg";
}
let l = theImages.length;
let generated = [];
//Function to pick a random image and display it
function showImage() {
let whichImage;
let newImage;
do {
whichImage = Math.round(Math.random() * (l - 1));
newImage = true;
for (let i = 0; i < generated.length; i++) {
if (generated[i] === whichImage) {
newImage = false;
break;
}
}
if (newImage) {
console.log("new: " + whichImage);
generated.push(whichImage);
} else {
console.log("already was generated: " + whichImage); //just to see if it works
}
} while (!newImage);
document.write('<img src="' + theImages[whichImage] + '" alt="A random painting of Steve Johnson"' + '>');
}
现在,如果我有 200 张图像并想显示 5 张,这很有效,但如果我想显示 9 张图像而我只有 10 张,结果很容易变成这样:
new: 8
paint.js:25 new: 0
paint.js:25 new: 7
paint.js:25 new: 5
paint.js:28 already generated: 8
paint.js:28 already generated: 5
paint.js:25 new: 3
paint.js:25 new: 9
paint.js:28 already generated: 8
paint.js:28 already generated: 3
paint.js:25 new: 6
paint.js:28 already generated: 7
paint.js:28 already generated: 3
paint.js:28 already generated: 6
paint.js:28 already generated: 5
paint.js:25 new: 1
paint.js:28 already generated: 6
paint.js:28 already generated: 5
paint.js:28 already generated: 6
paint.js:28 already generated: 7
paint.js:28 already generated: 3
paint.js:25 new: 2
这不是最佳选择。
我如何更改函数,以便它从数组中删除选取的图像,而不是在选取已使用的图像时重新滚动?我解决这个问题的想法是从数组中拼接“使用过的图像”,但我尝试的任何事情最终都会破坏某些东西。 在此先感谢您的帮助!
解决方法
是的,Array.prototype.splice 是最佳选择。它将从原始数组中删除一个项目,以便不能再次引用它。但是,由于数组是引用,它也会删除该项目,直到脚本重新启动。
为了不让原阵消失在时间的迷雾中,可以进行克隆。浅克隆适用于这种情况,因为该过程不会干扰数组中的任何内容。
一个 lot of ink 已经被用于在 javascript 中克隆东西,所以我不会在这里做。
以下示例只是从数组中获取随机数,但希望它可以帮助您弄清楚您需要什么。
function getRandomPickList(list,length) {
// Clone the original array as the function is going to destroy an array.
const clone = [...list];
// Just a spot to keep the picked values in.
const randomPick = [];
// Execute this loop until the randomPick array reaches the desired length
// or until the clone runs out of items.
while (randomPick.length < length && clone.length) {
// Add an item to the randomPick array.
randomPick.push(
// Remove an item from the input array.
clone.splice(
// Normal way to get random index from an array.
Math.floor(Math.random() * clone.length),1
)[0]
);
}
return randomPick;
}
const myNumbers = [0,1,2,3,4,5,6,7,8,9];
const newNumbersLength = 9;
console.log(getRandomPickList(myNumbers,newNumbersLength));
顺便说一句,Math.round 不应该用于从数组中获取随机项,因为如果 Math.random() 返回大于 1 - (1 / (l * 2))
的值,它会给您一个越界值。
对于一个简单的例子,考虑尝试从长度为 1 的数组中获取一个值。 Math.round(Math.random() * 1) 有 50% 的机会返回 1,但唯一有效的索引是 0。