Scott Montford
Scott Montford

Reputation: 165

How to make a random string generator that doesn't repeat strings

I am developing a "Never Have I Ever" webpage that generates Never Have I Ever scenarios everytime the user clicks a button.

I have the generator made, but the issue I am now faced with is that the generator keeps repeating the same strings after a few clicks.

Is there any way that would randomise what string has been picked but then not pick that string again?

 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];
}

Upvotes: 1

Views: 1014

Answers (4)

Aaron Plocharczyk
Aaron Plocharczyk

Reputation: 2832

What you really want is to shuffle the array and pop from it. That way the value isn't available for the next iteration. randojs.com makes common randomness stuff like this simple, so I used it in this answer.

//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>

Like I said, this answer uses randojs, so if you want to use this answer, just make sure you include this in the head tag of your HTML document near the top:

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

If you have any questions, leave me a comment!

Upvotes: 0

xdeepakv
xdeepakv

Reputation: 8125

You can create a generator function, which creates copy of quotes and return a closure function. On every call, get the random number, remove that element form copy.

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);
<pre id="random-quote"></pre>

Upvotes: 0

Sajeeb Ahamed
Sajeeb Ahamed

Reputation: 6390

You can do it by maintaining a hash object. Where you keep the index values which are already been displayed and generate random index until a unique index value is not generated.

 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>

Upvotes: 0

norbitrial
norbitrial

Reputation: 15166

You can use .filter() which removes an item by index based on the selected randomNumber from your array after presenting:

 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>

Probably you can add extra checking if you don't have more items in the array.

I hope this helps!

Upvotes: 1

Related Questions