0

I'm trying to create an array with three unique random numbers between 1 and 14. I've found similar questions on Stackoverflow and used the code to help me create my existing code.

It works well most of the time, but occasionaly it will create an array with two of the same numbers. Here is the offending code:

function noDuplicates (sideRandom) {
  sideArray.splice(sideRandom, 1);
  let sideRandom2 = Math.floor(Math.random() * 14) + 1;
  sideArray.push(sideRandom2);
  console.log("I've had to add " + sideRandom2)
}

function sortNumbers(array) {
  array.sort(function(a, b) {
    return a - b;
  });
}

document.getElementById("randomiser").addEventListener("click", function () {

  for (let i = 0; sideArray.length <3; i++) {
    let sideRandom = Math.floor(Math.random() * 14) + 1;

    console.log(sideRandom);
    if (sideArray.includes(sideRandom) === false) {
      sideArray.push(sideRandom);
    } else {
    noDuplicates(sideRandom);    
    };
  }    
  console.log(sideArray);
});

I suspect the issue is that sometimes the noDuplicates function generates the same random number as sideRandom, but I can't see a way around it. can you help?

David Webb
  • 31
  • 5
  • Does this answer your question? [Generating non-repeating random numbers in JS](https://stackoverflow.com/questions/18806210/generating-non-repeating-random-numbers-in-js) – Nick Aug 17 '20 at 09:26
  • Thanks for your help, Nick. I'm not sure whether whether the answers that question help or not. Bit of a noob... – David Webb Aug 17 '20 at 09:55

3 Answers3

2

Use set with while loop to make sure we got required number of unique random numbers

// Get unique random indexes
const random = (num, count) => {
  const set = new Set();
  while (set.size < count) {
    set.add(Math.floor(Math.random() * num) + 1);
  }
  return [...set];
};


document.getElementById("randomiser").addEventListener("click", function () {    
  console.log(random(14, 3));
});
<button id="randomiser"> Get 3 random </button> 
Siva K V
  • 10,561
  • 2
  • 16
  • 29
  • You don't inform the user for double and adding the new number. For the OP: If you want to know, how `Set` functions https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set – Sascha Aug 17 '20 at 10:16
  • Set is the correct choice here over array or list. But I feel your answer should explain what it is, just for completeness. Also, the numbers aren't ordered, like in the OP – UTF_or_Death Aug 17 '20 at 10:22
  • That's great - thamks for your contribution, Sivako! – David Webb Aug 17 '20 at 10:40
0

I take a look at your code: If there is a double you call noDuplicates and try to get a non double number but there you make some mistakes.

  • Why using Array#splice method? It will return the array without the first element (you don't user this result) and leave the original unchanged. So this line does anything. By the way why you want to delete the first element, youz didn't add the double random-number so there is anything do delete.
  • Afterwards you build another new randomnumber and push it to your array without checking. By this you get your dublettes.

Better way: If you finf a double set a flag on true and when you next add a number by this you can add your hint and reset the flag to false. So everything is one function.

document.getElementById("randomiser").addEventListener("click", function () {
  let sideArray = [];
  let double = false;
  for (let i= 0; sideArray.length <3; i++) {
    let sideRandom = Math.floor(Math.random() * 14) + 1;

    console.log(sideRandom);
    if (sideArray.includes(sideRandom) === false) {
      if (double) {
        double = false;
        console.log("I've had to add " + sideRandom);
      }
      sideArray.push(sideRandom);
    } else {
      double = true;  
    }
  }    
  console.log(sideArray.toString());
});
<button id='randomiser'>Click</button>
Sascha
  • 4,576
  • 3
  • 13
  • 34
  • Thank you, Sascha! That appears to work perfectly. I'm not quite sure WHY it works, though. How does it check for the existence of the duplicate? – David Webb Aug 17 '20 at 10:09
  • For this I used the variable `double` which I initialize with false and set it to true if there was a double, so by `if (double) {...}` I can inform the user and reset the flag to false. – Sascha Aug 17 '20 at 10:13
  • Thanks for your reply. But how does it know that the double variable is a duplicate number? – David Webb Aug 17 '20 at 10:19
  • By `if (sideArray.includes(sideRandom) === false) { ...} else { double = true};` you know that your new number is included in your sideArray. – Sascha Aug 17 '20 at 10:23
  • Thanks a lot, Sascha. I really appreciate your help! – David Webb Aug 17 '20 at 10:39
0

You can do this pretty easily with rando.js and slice. Plus, it's human-readable and cryptographically secure. randoSequence(1, 14) creates a shuffled array of all numbers from 1 through 14, and slice(0, 3) slices out the first three values from that shuffled array.

console.log(randoSequence(1, 14).slice(0, 3));
<script src="https://randojs.com/2.0.0.js"></script>
Aaron Plocharczyk
  • 2,776
  • 2
  • 7
  • 15