Home > Net >  What do I need to add to this code to stop the randomly generated images repeating themselves?
What do I need to add to this code to stop the randomly generated images repeating themselves?

Time:11-18

Hello I have tried to find a solution to this and am struggling. I am very new to Javascript! This code works to generate a random image on the button click but the images randomly repeat themselves. I want to show all the images but without repeating images already shown. I understand I should add a for loop and if statement but can't figure out how to write it. These are just a few example images in the array, I will actually have 55 images in the final thing. Can anyone help me!? Thank you! :)

Current code:

const imageArray = [
    "https://images.unsplash.com/photo-1508185159346-bb1c5e93ebb4?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=55cf14db6ed80a0410e229368963e9d8&auto=format&fit=crop&w=1900&q=80",
    "https://images.unsplash.com/photo-1495480393121-409eb65c7fbe?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=05ea43dbe96aba57d48b792c93752068&auto=format&fit=crop&w=1351&q=80",
    "https://images.unsplash.com/photo-1501611724492-c09bebdba1ac?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=ebdb0480ffed49bd075fd85c54dd3317&auto=format&fit=crop&w=1491&q=80",
    "https://images.unsplash.com/photo-1417106338293-88a3c25ea0be?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=d1565ecb73a2b38784db60c3b68ab3b8&auto=format&fit=crop&w=1352&q=80",
    "https://images.unsplash.com/photo-1500520198921-6d4704f98092?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=ac4bc726064d0be43ba92476ccae1a75&auto=format&fit=crop&w=1225&q=80",
    "https://images.unsplash.com/photo-1504966981333-1ac8809be1ca?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=9a1325446cbf9b56f6ee549623a50696&auto=format&fit=crop&w=1350&q=80"
];

const image = document.querySelector("img");
const button = document.querySelector("button");

window.onload = () => generateRandomPicture(imageArray);

button.addEventListener("click", () => generateRandomPicture(imageArray));

function generateRandomPicture(array){
    let randomNum = Math.floor(Math.random() * array.length); 
    image.setAttribute("src", array[randomNum]);
}

CodePudding user response:

This should clearly explain how to do this using event listeners and the well-known Fisher-Yates shuffle algorithm. If the first item of the shuffled array matches the current image, the shuffle gets repeated (via a do-while loop) to avoid showing the same image twice in a row.

window.addEventListener('DOMContentLoaded', () => {

  // Identifies DOM elements and other constants
  const
    changeButton = document.getElementById("change-button"),
    displayDiv = document.getElementById("display-div"),
    imageArray = ["image 1", "image 2", "image 3", "image 4", "image 5"],
    HIGHEST_INDEX = imageArray.length - 1;

  // Calls `changeImage` whenever changeButton is clicked
  changeButton.addEventListener("click", changeImage);

  // Forces shuffle on first click
  let currentIndex = HIGHEST_INDEX;

  // Defines listener for click events
  function changeImage(){

    // If we're at the end of the array, we need to shuffle...
    if(currentIndex == HIGHEST_INDEX){

      // Remembers the current image
      const currentImage = imageArray[currentIndex];

      // Keeps calling `shuffle` until next image ≠ current image
      do { shuffle(imageArray); }
      while (imageArray[0] === currentImage);
      
      // Prepares to start from beginning of shuffled array
      currentIndex = -1;
    }
    
    //Regardless, increments index and shows corresponding image 
    displayDiv.textContent = imageArray[  currentIndex];
  }


  // Implements Fisher-Yates shuffle
  function shuffle(arr, randIndex=NaN, temp=null){

    // Starts i at the highest index & works backwards through array
    let i = arr.length - 1;
    while(i-- > 0){   
      
      // Gets random index from remaining (unswapped) indexes
      rand = Math.floor(Math.random() * (i   1));

      // Swaps the value at the random index with the value at i
      temp = arr[rand];
      arr[rand] = arr[i];
      arr[i] = temp;
    }
  }
});
#display-div {margin-top: 0.5em; }
<button id="change-button">CHANGE IMAGE</button>
<div id="display-div"></div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

I think this is more like what you were trying to do. (My other answer allowed for cycling through the same list repeatedly and randomizing it each time, but for bingo you don't need all that.)

The populateImgs function takes a list of urls and loops through all the img elements on the page, setting each src attribute to a different url, or failing if there are too few urls to fill all the imgs. When the function gets called, the urls argument is built on the fly from a shuffled list of partial urls. (The resulting urls are shorter than your original urls, which included a lot of parameters that I omited for brevity.)

The shuffle function uses the same algorithm but implemented a bit differently (using the cleaner-looking while(--i > 0){ swap(array, i, randLessThan(i)); }).

window.addEventListener('DOMContentLoaded', function(){

  // Defines an array of strings that identify photos
  const photoIds = [
    "1508185159346-bb1c5e93ebb4", "1495480393121-409eb65c7fbe",
    "1501611724492-c09bebdba1ac", "1417106338293-88a3c25ea0be",
    "1500520198921-6d4704f98092", "1504966981333-1ac8809be1ca"
  ];        

  // Calls `populateImgs`, w/ a list of randomized urls based on photoIds
  populateImgs(
    shuffle(photoIds).map(id => `https://images.unsplash.com/photo-${id}`)
  );


  function populateImgs(urls){
    // Shows one photo in each img element
    const imgs = document.querySelectorAll("img");        
    if(urls.length < imgs.length){ return console.log("Not enough photos"); }
    
    let index = -1;
    while (  index < imgs.length){
      imgs[index].setAttribute("src", urls[index]);
    };
  }

  function shuffle(array){
    // Uses helper functions to randomize array, returns randomized array

    const
      randLessThan = (num) => Math.floor(Math.random() * num),
      swap = (arr, i, rand) => { let temp=arr[rand]; arr[rand]=arr[i]; arr[i]=temp; };

    // Iterates backwards, swaps each item with a random earlier item, ignores i==0
    let i = array.length;
    while(--i > 0){ swap(array, i, randLessThan(i)); }
    return array; 
  }

});
img{ width: 100px; height: 80px; object-fit: cover; margin: 15px; }
<div class="row">
  <img/><img/>
</div>
<div class="row">
  <img/><img/>
</div>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related