【问题标题】:How to make a random string generator that doesn't repeat strings如何制作不重复字符串的随机字符串生成器
【发布时间】:2020-04-11 13:27:46
【问题描述】:

我正在开发一个“我从未有过”网页,每次用户单击按钮时都会生成“我从未有过”场景。

我已经制作了生成器,但我现在面临的问题是生成器在单击几下后不断重复相同的字符串。

有没有什么方法可以随机化选择的字符串,然后不再选择该字符串?

 var scenario = [
    'Never Have I Ever 1',
    'Never Have I Ever 2',
    'Never Have I Ever 3',
    'Never Have I Ever 4',
    'Never Have I Ever 5',
    'Never Have I Ever 6',
    'Never Have I Ever 7',
    'Never Have I Ever 8',
    'Never Have I Ever 9',
    'Never Have I Ever 10',
    'Never Have I Ever 11',
    'Never Have I Ever 12',
    'Never Have I Ever 13',
    'Never Have I Ever 14',
    'Never Have I Ever 15',
    'Never Have I Ever 16',
    'Never Have I Ever 17',
    'Never Have I Ever 18'
]

function generate() {
    var randomNumber = Math.floor(Math.random() * (scenario.length));
    document.getElementById("sentence").innerHTML = scenario[randomNumber];
}

【问题讨论】:

  • 您可以在游戏第一次启动时对数组进行洗牌,然后在您想要获得新场景时使用.pop() 一个字符串(也许将其推回到数组的开头,这样您就可以循环也许通过场景)

标签: javascript arrays random generator


【解决方案1】:

您可以使用.filter(),它根据在呈现后从您的数组中选择的randomNumber 按索引删除一个项目:

 let scenario = ['Never Have I Ever 1', 'Never Have I Ever 2', 'Never Have I Ever 3', 'Never Have I Ever 4', 'Never Have I Ever 5', 'Never Have I Ever 6', 'Never Have I Ever 7', 'Never Have I Ever 8', 'Never Have I Ever 9', 'Never Have I Ever 10', 'Never Have I Ever 11', 'Never Have I Ever 12', 'Never Have I Ever 13', 'Never Have I Ever 14', 'Never Have I Ever 15', 'Never Have I Ever 16', 'Never Have I Ever 17', 'Never Have I Ever 18'];

function generate() {
    const randomNumber = Math.floor(Math.random() * (scenario.length));
    let sentence = 'No more sentences';

    if (scenario.length > 0) {
       sentence = 
scenario[randomNumber];
       scenario = scenario.filter((e, i) => i !== randomNumber);
       console.log('length of remaining scenario items:', scenario.length);
    }

    document.getElementById("sentence").innerHTML = sentence;
}

generate();
<div id="sentence"></div>
<button onclick="generate()">Generate new sentence</button>

如果数组中没有更多项目,您可能可以添加额外的检查。

我希望这会有所帮助!

【讨论】:

    【解决方案2】:

    您可以通过维护一个哈希对象来做到这一点。保留已显示的索引值并生成随机索引,直到不生成唯一索引值为止。

     let scenario = ['Never Have I Ever 1', 'Never Have I Ever 2', 'Never Have I Ever 3', 'Never Have I Ever 4', 'Never Have I Ever 5', 'Never Have I Ever 6', 'Never Have I Ever 7', 'Never Have I Ever 8', 'Never Have I Ever 9', 'Never Have I Ever 10', 'Never Have I Ever 11', 'Never Have I Ever 12', 'Never Have I Ever 13', 'Never Have I Ever 14', 'Never Have I Ever 15', 'Never Have I Ever 16', 'Never Have I Ever 17', 'Never Have I Ever 18'];
    
    const btn = document.querySelector('#generator');
    const display = document.querySelector('#display');
    let hash = {};
    let clickCount = 0;
    
    btn.addEventListener('click', function(e) {
    	e.preventDefault();
      const {length} = scenario;
      let randomIndex = Math.floor(Math.random() * length);
      
      while (hash[randomIndex] !== undefined) {
      	randomIndex = Math.floor(Math.random() * length);
      }
      
     if (clickCount > length) {
      	hash = {};
        alert('Added all strings');
      }
      
      hash[randomIndex] = 1;
      display.innerText += scenario[randomIndex] + "\n";
      clickCount++;
    });
    <div id="display"></div>
    <button id="generator">Generate</button>

    【讨论】:

      【解决方案3】:

      您可以创建一个生成器函数,该函数创建copy of quotes 并返回一个closure function。在每次通话时,获取随机的 number,删除该 element 表单副本。

      function generate(scenario) {
        let copy = [...scenario];
        return function () {
          const randomNumber = Math.floor(Math.random() * copy.length);
          const data = copy[randomNumber];
          copy.splice(randomNumber, 1);
          return data;
        };
      }
      
      const quotePre = document.getElementById("random-quote");
      const scenario = ["Never Have I Ever 1","Never Have I Ever 2","Never Have I Ever 3","Never Have I Ever 4","Never Have I Ever 5","Never Have I Ever 6","Never Have I Ever 7","Never Have I Ever 8","Never Have I Ever 9","Never Have I Ever 10","Never Have I Ever 11","Never Have I Ever 12","Never Have I Ever 13","Never Have I Ever 14","Never Have I Ever 15","Never Have I Ever 16","Never Have I Ever 17","Never Have I Ever 18"];
      
      const randomGenerator = generate(scenario);
      setInterval(function () {
        const quote = randomGenerator();
        if (quote) quotePre.innerText = quote;
      }, 1000);
      &lt;pre id="random-quote"&gt;&lt;/pre&gt;

      【讨论】:

        【解决方案4】:

        您真正想要的是将数组和pop 从中洗牌。这样该值就不能用于下一次迭代。 randojs.com 使常见的随机性变得如此简单,因此我在此答案中使用了它。

        //define scenarios
        var scenarios = ['Never Have I Ever 1', 'Never Have I Ever 2', 'Never Have I Ever 3'];
        
        //make a shuffled copy of scenarios
        var shuffledScenarios = randoSequence(scenarios);
        
        function generate(){
          //refill the shuffled array if needed
          if(shuffledScenarios.length == 0) shuffledScenarios = randoSequence(scenarios);
          
          //remove a value from the shuffled array and output it
          console.log(shuffledScenarios.pop().value);
        }
        <script src="https://randojs.com/1.0.0.js"></script>
        <button onclick="generate()">Show the next one</button>

        就像我说的,这个答案使用了randojs,所以如果你想使用这个答案,只要确保你在靠近顶部的HTML文档的head标签中包含这个:

        <script src="https://randojs.com/1.0.0.js"></script>
        

        如果你有任何问题,请给我留言!

        【讨论】:

          猜你喜欢
          • 2017-04-05
          • 2018-01-06
          • 2010-12-07
          • 2015-08-16
          • 1970-01-01
          • 2010-11-10
          • 2011-08-06
          相关资源
          最近更新 更多