Reputation: 165
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
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
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
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
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