Reputation: 13
How can I randomly generate numbers without repetition in this case?
let lottoArray = [];
lottoGame()
function lottoGame () {
do {
let addNumber = Math.floor(Math.random()* 30);
lottoArray.push(addNumber)
console.log(addNumber)
} while(lottoArray.length <= 5 ) {
}
document.querySelector('.loti').innerHTML = lottoArray
}
Upvotes: 0
Views: 300
Reputation: 3434
You are already keeping track of the numbers. Now we just have to repeat the randomization until we find a number we don't already have.
We can use Array.includes()
to see if the number is already added, and continue
to skip to the next iteration. Skipping forward means we also skip the lottoArray.push(addNumber)
part.
I removed the empty {}
(curly brackets) after while(…)
since it is a do…while loop, it doesn't have a trailing block. I also removed your console.log()
, and instead added <p class="loti"></p>
to your HTML for output.
let lottoArray = [];
lottoGame();
function lottoGame() {
do {
let addNumber = Math.floor(Math.random()* 30);
if (lottoArray.includes(addNumber)) continue;
lottoArray.push(addNumber);
} while(lottoArray.length <= 5);
document.querySelector('.loti').innerHTML = lottoArray;
}
<p class="loti"></p>
You should also take a look at iota's answer. He uses a Set
which can hold an element only once, which is perfect for this scenario.
One could also solve it by transferring elements from one list to another, where the other is the list holding the "drawn" elements. This can also be used where the elements aren't conveniently numbers that can be generated using Math.random()
.
Here is the lotto game using the "transfer elements"-technique:
var numbersDrawn;
var numbersLeft;
var maxDraws;
newGame(); // Reset game
// Add listeners
document.querySelector('button').addEventListener('click', drawNumber);
document.querySelector('button:last-of-type').addEventListener('click', newGame);
// Draw a random number; update <p>-elements
function drawNumber() {
if (numbersDrawn.length == maxDraws) return;
// This takes away a number from 'numbersLeft' and adds it to 'numbersDrawn'
numbersDrawn.push(
numbersLeft.splice(Math.floor(Math.random() * numbersLeft.length), 1));
document.querySelector('#lotto-draws-left').textContent =
'Draws left: ' + (maxDraws - numbersDrawn.length);
document.querySelector('#lotto-output').textContent = numbersDrawn.join(', ');
}
// Reset game-state
function newGame() {
// These values may be changed
var _maxNumbers = 60;
var _maxDraws = 6;
numbersDrawn = [];
numbersLeft = range(1, _maxNumbers); // Create array of range [1, ..., maxNumbers]
maxDraws = _maxDraws;
// Reset <p>-elements' text
document.querySelector('#lotto-draws-left').textContent = 'Draws left: ' + maxDraws;
document.querySelector('#lotto-output').textContent = '';
}
// Creates an array with numbers of range [min, max]: [min, ..., max]
function range(min, max) {
return [...new Array(max - min + 1).keys()].map(i => i + min);
}
<button>Draw number</button>
<button>New game</button>
<p id="lotto-draws-left"></p>
<p id="lotto-output"></p>
And here is an example for a "non-number drawing" scenario:
var deck;
var hand;
newGame();
document.querySelector('button').addEventListener('click', drawCard);
document.querySelector('button:last-of-type').addEventListener('click', newGame);
function drawCard() {
if (deck.length <= 0) return;
// Same again, taking from 'deck', adding to 'hand'
hand.push(deck.splice(Math.floor(Math.random() * deck.length), 1));
var listHand = document.querySelector('#hand');
listHand.innerHTML = '';
hand.forEach(i => {listHand.innerHTML += `<li>${i}</li>`}); // Add a <li> for each element in 'hand'
}
function newGame() {
// Yes, '_deck' can be generated easier, however this is just for demonstration purposes
var _deck = ['1. Magnificent Text', '2. Beautiful Text', '3. Gorgeous Text', '4. Extraordinary Text', '5. Charming Text', '6. Stunning Text', '7. Graceful Text', '8. Exquisite Text', '9. Bewitching Text', '10. Aesthetic Text', '11. Decorative Text', '12. Sightly Text', '13. Unlucky Text', '14. Pulchritudinous Text', '15. Elegant Text', '16. Appealing Text', '17. Lovely Text', '18. Dazzling Text', '19. Captivating Text', '20. Marvelous Text', '21. Admirable Text', '22. Mesmerizing Text', '23. (Repetitive) Charming Text', '24. Adorable Text', '25. Alluring Text'];
hand = [];
deck = _deck.slice(); // Copy '_deck'
document.querySelector('#hand').innerHTML = '';
}
<button>Draw card</button>
<button>New game</button>
<ul id="hand"></ul>
Upvotes: 0
Reputation: 15847
You can create an array of the numbers that you want to choose from. Then simply remove the number when it is pulled.
function lottoGame(max_numbers) {
let lottoArray = [];
let numbers = [];
let max_num = 6;
for (var i = 1; i <= max_num; i++) {
numbers.push(i);
}
nums = [];
for (let x = 1; x <= max_numbers; x++) {
rand = Math.floor(Math.random() * numbers.length);
num = numbers[rand];
nums.push(num);
numbers.splice(rand, 1);
}
document.querySelector('.loti').innerHTML = nums.join(",")
}
lottoGame(5)
<div class="loti"></div>
Upvotes: 2
Reputation: 5004
You can check if the value is already in the array if not then push it in the array
To check if the array contains the value you can use the method includes()
function lottoGame () {
let lottoArray = [];
do {
let addNumber = Math.floor(Math.random()* 30);
if(!(lottoArray.includes(addNumber)) && addNumber > 0){
lottoArray.push(addNumber)
}
} while(lottoArray.length <= 5 )
return lottoArray;
}
let arr = lottoGame();
console.log(arr);
document.querySelector('.loti').textContent = [...arr];
<div class="loti"></div>
Upvotes: 1
Reputation: 8329
Here's a pretty easy lotto game. You can set the range of numbers and the number of numbers picked from the range.
// setting up lotto game parameters
const RANGE_MAX = 90 // range of numbers
const NO_NUMBERS = 5 // how many to choose
const lottogame = (rangeMax, noNumbers) => {
const range = []
let result = []
for (let i = 0; i < rangeMax; i++) {
range.push(i + 1)
}
for (let i = 0; i < noNumbers; i++) {
const num = range.splice(randomIntFromInterval(0, range.length - 1), 1)[0] // splice removes the item from the array
result.push(num)
}
return result
}
console.log(lottogame(RANGE_MAX, NO_NUMBERS).sort((a, b) => a - b))
// random function
// source: https://stackoverflow.com/questions/4959975/generate-random-number-between-two-numbers-in-javascript
function randomIntFromInterval(min, max) { // min and max included
return Math.floor(Math.random() * (max - min + 1) + min);
}
Upvotes: 1
Reputation: 89214
You can use a Set
(which only contains unique elements) to store the numbers.
let lotto = new Set;
lottoGame()
function lottoGame () {
do {
let addNumber = Math.floor(Math.random()* 30);
lotto.add(addNumber)
console.log(addNumber)
} while(lotto.size <= 5 );
document.querySelector('.loti').textContent = [...lotto];
}
<div class="loti"></div>
Upvotes: 1
Reputation: 1
I don't know if there is a better solution. Yet I would just check if the array already contains the number before pushing the number in it. If yes, I would randomize again.
Upvotes: 0