如何编写一个循环生成器,它从消息数组中随机选择项目,但在每个项目显示一次之前不重复单个项目?

How to write a cyclic generator which randomly picks items from a message array but does not repeat a single item until every item was displayed once?

我需要一个消息生成器来生成包含在数组中的报价。但我必须:

  1. 确保每条随机显示的消息仅显示 1 次,直到显示所有消息/在显示所有消息之前没有重复。

  2. 当所有消息显示完毕后,再次允许所有消息并重复2.

这就是我到目前为止得出的结论:

let btn = document.getElementById('btn');
let output = document.getElementById('output');

let quotes = [
  'No one is perfect - that’s why pencils have erasers. - Wolfgang Riebe',
  'Have no fear of perfection - you will never reach it. - Salvador Dali',
  'The tallest mountain started as a stone. - One Punch Man Intro',
  'Make it work. Make it nice. Make it fast. Always obey this order! - kiraa',
  'A good programmer is someone who always looks both ways before crossing a one-way street. – Doug Linder',
  'If debugging is the process of removing software bugs, then programming must be the process of putting them in. - Edsger W. Dijkstra',
];

btn.addEventListener('click', function() {
  let randomQuote = quotes[Math.floor(Math.random() * quotes.length)]
  output.innerHTML = randomQuote;
})
#container {
  background-color: mediumpurple;
  border: 5px solid white;
  height: 300px;
  width: 700px;
  margin: 0 auto;
  text-align: center;
  border-radius: 25px;
}
#btn {
  margin:  50px auto;
  height: 50px;
  width: 250px;
  font-size: 20px;
  background-color: white;
  font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
  border-radius: 30px;
}

output {
  margin: 25px auto;
  font-size: 20px;
  color: white
}
<div id="container">
  <button id="btn">Get your message of the day</button>

  <div id="output"> Press it :)</div>
</div>

一种可能的方法是创建一个点击处理程序,它可以访问绑定的原始数组,也可以改变前者的绑定(总是自我牺牲)副本。

万一 sacrifice ...通过 constantly/repeatedly 从中切出一个随机 quote/string 到 deplete/mutate 的数组 ... 未提供或是空的,确实将原始数组的新浅表副本分配给处理程序 this-context。因此处理程序再次开始操作一组 renewed/complete 报价项目 ...

function depleteAndDisplayBoundQuotesRandomlyAndRepeat () {
  let { output, original, sacrifice } = this;
  if (
    !Array.isArray(sacrifice) ||
    (sacrifice.length === 0)
  ) {
    sacrifice = this.sacrifice = Array.from(original);
  }
  // console.log(sacrifice);

  const idx =
    Math.floor(Math.random() * sacrifice.length);

  // mutate/deplete the sacrifice quotes array.
  const quote = sacrifice.splice(idx, 1);

  output.textContent = quote;
}

const quotes = [
  'No one is perfect - that’s why pencils have erasers. - Wolfgang Riebe',
  'Have no fear of perfection - you will never reach it. - Salvador Dali',
  'The tallest mountain started as a stone. - One Punch Man Intro',
  'Make it work. Make it nice. Make it fast. Always obey this order! - kiraa',
  'A good programmer is someone who always looks both ways before crossing a one-way street. – Doug Linder',
  'If debugging is the process of removing software bugs, then programming must be the process of putting them in. - Edsger W. Dijkstra',
];

document
  .querySelector('#btn')
  .addEventListener('click',
    depleteAndDisplayBoundQuotesRandomlyAndRepeat.bind({
      output: document.querySelector('#output'),
      original: quotes,
    })
  );
#container {
  background-color: mediumpurple;
  border: 5px solid white;
  height: 300px;
  width: 700px;
  margin: 0 auto;
  text-align: center;
  border-radius: 25px;
}
#btn {
  margin:  50px auto;
  height: 50px;
  width: 250px;
  font-size: 20px;
  background-color: white;
  font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
  border-radius: 30px;
}

output {
  margin: 25px auto;
  font-size: 20px;
  color: white
}
<div id="container">
  <button id="btn">Get your message of the day</button>

  <div id="output"> Press it :)</div>
</div>