我怎样才能将这个随机图像选择器功能转换为拼接所选图像的功能?

问题描述

我对编码非常陌生(大约 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。