0

So I'm making a javascript lottery with 6 random generated numbers. Does anybody know how to prevent those numbers from being the same?

Thanks

Code:

'use strict';
function generatenumbers(){
    let number = [];
    let i;
    i=0;
    for(i= 0; i <= 5; i++){
        number[i] = Math.floor(Math.random()*40);
    }
    document.getElementById("generated").innerHTML = "";
    i = 0;
    for(i=0; i<= number.length - 1; i++){
        let node = document.createElement("LI");
        let txt = document.createTextNode(number[i]);
        node.appendChild(txt);
        document.getElementById("generated").appendChild(node);
    }
}

HTML:

<body>
<div id="container" class="cf">
    <header>
        <h1>Hipster Powered Lottery</h1>

    </header>

    <section>
        <h2>Play with our wonderful lottery est. 1831</h2>
        <a href="#" id="generate" onclick="generatenumbers()">Generate my numbers!</a>
        <ul id="generated"></ul>

    </section>
    <aside>
        <h2>Previously generated set</h2>
        <ul id="previous"></ul>

    </aside>
</div>
</body>

2 Answers2

1

When creating a random number, only use one that isn't yet in your array:

var number = [];
for(i= 0; i <= 5; i++){
    var num;
    while ( number.includes( num = Math.floor(Math.random()*40) ) );
    number[i] = num;
}
console.log(number);

The empty while loop repeatedly selects a number until it finds one that isn't in the number array. Only after that successfully finishes does it then add that number to the array.

Makyen
  • 31,849
  • 12
  • 86
  • 121
kmoser
  • 8,780
  • 3
  • 24
  • 40
  • Is this code correct cause it will give an error for the while loop right? –  Nov 24 '19 at 17:43
  • I tested this code and it works. The loop just has no body, which (while unusual) is perfectly legit. – kmoser Nov 24 '19 at 17:45
  • For some reason if I implement this code, the numbers are not added to the list (2nd for loop in my code) –  Nov 24 '19 at 17:49
  • main.js:16 Uncaught TypeError: Cannot read property 'appendChild' of null at generatenumbers (main.js:16) at HTMLAnchorElement.onclick (VM36 index.html:21) –  Nov 24 '19 at 17:51
  • thats the fault –  Nov 24 '19 at 17:51
  • do you have a solution to that? –  Nov 24 '19 at 18:04
  • What's the code on line 16? I'm guessing it's ``document.getElementById("generated")`` which is failing because it can't find that element with an id of ``generated``. Can you post your HTML? – kmoser Nov 24 '19 at 18:08
  • ive added the html, thank you in advance –  Nov 24 '19 at 18:14
  • 1
    While this approach (usually) works for getting 6 unique out of 40, it's not a good approach for the general problem of getting N unique out of Y (e.g. generate a random order for a deck of 52 cards). The reason it's not a good general approach is that as N approaches Y, the algorithm will, on average, take longer and longer to get each additional unique number. Given that the numbers for selecting which number to use are random, there are sequences of random numbers which result in this algorithm taking an unbounded amount of time, even in the 6 unique out of 40 case (even if quite unlikely). – Makyen Nov 24 '19 at 18:26
  • @thr You need to declare `i` like this: ``for(var i= 0; i <= 5; i++)...`` – kmoser Nov 24 '19 at 19:01
  • @Makyen Agreed, but there are several ways to do this depending on the order of magnitude of the number of random numbers, how much memory you want to use, and how fast you want your algorithm to run. There is no single correct answer. My solution, while not as fast as it could be, has the advantage of being easy to read, and should be more than sufficiently efficient in the case of 6 random numbers.. – kmoser Nov 24 '19 at 19:06
  • @kmoser I agree, there are several different ways to do this. A more general answer (i.e. better) would explain at least some of those options and the reasons for picking them, or not picking them, under various conditions. Keep in mind: answers on Stack Overflow are intended more to be useful to future visitors than they are intended to help the question OP with their specific problem. An answer which describes the general solutions to pick N of Y is significantly better, and can be better used as a duplicate-target, than answers which solve *just* the problem which the question OP presents. – Makyen Nov 24 '19 at 19:23
0

random() function generates number randomly so there is a possibility that one number can occur again. To avoid that once a new number is generated by random() function you can check whether this number is already present in your array or not. Add it to your array only if it is not already present. A working snippet is provided below:

function generatenumbers(){
   var number = new Array();
   var i=0;
   while(i<6){
   var val = Math.floor(Math.random()*40);
   if(number.includes(val) === false){
      number.push(val);
      i++;
     }
   }
   document.getElementById("generated").innerHTML = "";
   i = 0;
   for(i=0; i<= number.length - 1; i++){
      let node = document.createElement("LI");
      let txt = document.createTextNode(number[i]);
      node.appendChild(txt);
      document.getElementById("generated").appendChild(node);
   }
}
Himanshu Singh
  • 2,117
  • 1
  • 5
  • 15
  • could you adapt it a little bit more to my code above please? –  Nov 24 '19 at 17:53
  • @thr sure give me a minute – Himanshu Singh Nov 24 '19 at 17:54
  • @thr i have updated could you pls check. – Himanshu Singh Nov 24 '19 at 18:08
  • dude , youre a legend. Do you by any chance know a replacement for getElementByID for this code? –  Nov 24 '19 at 18:17
  • While this approach (usually) works for getting 6 unique out of 40, it's not a good approach for the general problem of getting N unique out of Y (e.g. generate a random order for a deck of 52 cards). The reason it's not a good general approach is that as N approaches Y, the algorithm will, on average, take longer and longer to get each additional unique number. Given that the numbers for selecting which number to use are random, there are sequences of random numbers which result in this algorithm taking an unbounded amount of time, even in the 6 unique out of 40 case (even if quite unlikely). – Makyen Nov 24 '19 at 18:28
  • Himanshu, some food for thought. In general, if you have to do all the work for a question author here, and then they ask for more modifications/work from you, the chances are that they will keep doing that on Stack Overflow until they are stopped. We don't really want these sorts of questions here, as they are usually too localised, and we certainly would rather every question author made a good-faith effort before asking other people to do their work. – halfer Nov 24 '19 at 18:50
  • In particularly egregious cases, this can make you vulnerable to downvotes, as some readers would rather such questions were put on hold immediately, in order to preserve the quality of the question set here. Some readers thus may downvote on answers in order to discourage people from encouraging low-effort questions. – halfer Nov 24 '19 at 18:51
  • 1
    @halfer even I’m new on SO and you made a reasonable point. From next time onwards I’ll keep this in mind. – Himanshu Singh Nov 24 '19 at 19:31