Pan Ogóras
Pan Ogóras

Reputation: 13

Random Numbers without repeat. Beginner Lvl

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

Answers (6)

Oskar Grosser
Oskar Grosser

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

imvain2
imvain2

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

Aalexander
Aalexander

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

muka.gergely
muka.gergely

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

Unmitigated
Unmitigated

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

Alisson
Alisson

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

Related Questions