简体   繁体   English

如何从随机化数组的 output 的 function 中排除 output?

[英]How can I exclude a output from a function that randomizes the output of an array?

I'm quite new to JavaScript so bear with me please.我对 JavaScript 很陌生,所以请多多包涵。 I'm trying to randomize the outcome of an event listener function.我正在尝试随机化事件侦听器 function 的结果。 When the Element (the divs in the element) are clicked there supposed to change color to a random color from the set.当单击元素(元素中的 div)时,应该将颜色更改为集合中的随机颜色。 They change color, but not to a different color.它们会改变颜色,但不会改变颜色。 Sometimes, because it's randomized it "changes" to the same color.有时,因为它是随机的,所以它“改变”为相同的颜色。 I don't really want this to happen.我真的不希望这种情况发生。

What I've tried is making a function that picks a color and then checks if that color is already being 'used',but it didn't work because there where multiple functions inside a function and they didn't properly interact or I couldn't figure out ho to access them.我尝试的是制作一个 function 来选择一种颜色,然后检查该颜色是否已经被“使用”,但它不起作用,因为 function 中有多个功能,它们没有正确交互,或者我不能不知道如何访问它们。

what I also tried, was making a second array called b=[] then adding the current color, and then checking whether the random color was present and if it was running the function again to generate a new random color.我还尝试过创建第二个名为b=[]的数组,然后添加当前颜色,然后检查随机颜色是否存在以及是否再次运行 function 以生成新的随机颜色。

ad = document.querySelectorAll(".all div")
colors = ['yellow', 'red', 'blue', 'cornsilk']

ad.forEach((f, index) =>{
    var cc = ad[index].style.backgroundColor;
    f.addEventListener('click', ()=>{
      function makeColor(cc){
        newColor = colors[Math.floor(Math.random()*colors.length)]
        if (newColor == cc){
          makeColor();
        }
        else{
          return newColor;
        };
      };
      var a = makeColor();
      ad[index].style.backgroundColor = newColor;
    });
  });
// this almost works. It changes the colours but not to different ones.

you can use a set to track used colors, repick colors until an unused color, then add new color to set and remove original color.您可以使用一组来跟踪使用过的 colors,重新选择 colors 直到未使用的颜色,然后添加新颜色以设置和删除原始颜色。

 ad = document.querySelectorAll(".all div") colors = ['yellow', 'red', 'blue', 'cornsilk'] const used = new Set() // track used colors ad.forEach((f, index) => { f.addEventListener('click', () => { function makeColor(cc) { newColor = colors[Math.floor(Math.random() * colors.length)] // repick until unused color while (used.has(newColor)) newColor = colors[Math.floor(Math.random() * colors.length)] }; // current color var cc = ad[index].style.backgroundColor; var a = makeColor(); ad[index].style.backgroundColor = newColor; used.add(newColor); // add new color to set used.delete(cc); // remove old color from set }); });
 <div class="all"> <div>1</div> <div>2</div> <div>3</div> </div>

First declare the function in global scope.首先在全局 scope 中声明 function。 A do... while loop could be a solution.一个do... while循环可能是一个解决方案。

 ad = document.querySelectorAll(".all div") colors = ['yellow', 'red', 'blue', 'cornsilk'] ad.forEach((f, index) => { f.addEventListener('click', (el) => { ad[index].style.backgroundColor = makeColor(el.currentTarget.style.backgroundColor); }); }); function makeColor(cc) { if (colors.length) { var newColor = colors[Math.floor(Math.random() * colors.length)]; colors.splice(colors.indexOf(newColor), 1); if (cc) colors.push(cc); return newColor; } else { return cc; } };
 .all { display: flex; }.all div { margin: 2px; width: 100px; height: 100px; border: 1px solid #666; }
 <div class="all"> <div></div> <div></div> <div></div> </div>

This is much simpler than you are making it.这比你做的要简单得多。 Just remove the color from the array after it's been used and instead of looping and setting the event on each element, just set it on the parent and then access the initiating element with event.target .只需在使用后从数组中删除颜色,而不是在每个元素上循环和设置事件,只需在父元素上设置它,然后使用event.target访问初始元素。

Also, make sure you always declare your variables.另外,请确保您始终声明您的变量。

 let ad = document.querySelector(".all"); let colors = ['yellow', 'red', 'blue', 'cornsilk']; let newColor = ""; ad.addEventListener('click', function makeColor(event){ if(colors.length){ newColor = colors[Math.floor(Math.random() * colors.length)]; event.target.style.backgroundColor = newColor; // Simply remove the used color from the array so it can be used again colors.splice(colors.indexOf(newColor),1); console.log(colors.join()); } else { console.log("No more colors to pick from;"); } });
 <div class="all"> <div>Item</div> <div>Item</div> <div>Item</div> <div>Item</div> </div>

You have the right thinking, but you should start with an array that will always give you want you want instead of hoping it will give you want you want.你有正确的想法,但你应该从一个总是给你想要的数组开始,而不是希望它会给你想要的。

One suggestion is to read up on the this context in event handlers as that can simplify your code a lot like below.一个建议是阅读事件处理程序中的this上下文,因为这可以简化您的代码,如下所示。

For each click we will use this (the clicked div) to get the current color, then you can filter out that current color, so you're left with an array with all the colors, but that one.对于每次单击,我们将使用this (单击的 div)来获取当前颜色,然后您可以过滤掉当前颜色,因此您会得到一个包含所有 colors 的数组,但只有那个。

Now your makeColor() will just work since it has an array that is meant for it to begin with.现在你的 makeColor() 将正常工作,因为它有一个数组,它意味着它开始。

 ad = document.querySelectorAll(".all div") colors = ['yellow', 'red', 'blue', 'cornsilk'] ad.forEach(f => { f.addEventListener('click', function() { let cc = this.style.backgroundColor; let diffColors = colors.filter(color => color;== cc). function makeColor() { return diffColors[Math.floor(Math.random() * colors;length)] }. this.style;backgroundColor = makeColor(); }); });
 <div class="all"> <div>hello</div> </div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM