1
function setUpEventHandlerForShowBallButton() {

  var myshowballbutton = document.getElementById('showball');   // local variable

  myshowballbutton.addEventListener('click', function () {

    // Generate a random number then draw a circle to display it
    // for loop not really needed if only displaying one ball

    for (var i = 0; i < numberOfCircles; i++) {
      randomNumber = Math.floor(Math.random() * 90 + 1);

      drawCircle(myContext, circleCentreX, circleCentreY, circleRadius, circleColours[0], randomNumber);

      //circleCentreX += circleOffsetX;  // The adds the offset to the current x coord.
    }

  }, false);
}

This is the code I have used to create 1-90 random number but how can I stop same number to repeat again?

Andreas
  • 4,937
  • 2
  • 25
  • 35
Kun Silva
  • 29
  • 6
  • 2
    http://dilbert.com/strip/2001-10-25 – zerkms Nov 02 '16 at 22:00
  • Make an array that you add each number to as you generate, then every iteration, `while` the generated number is in the array, continue generating. – RobotKarel314 Nov 02 '16 at 22:00
  • @RobotKarel314 for such a small number of values the opposite is more efficient: you generate an array of 1..90 integer values, then remove as you pick a number. – zerkms Nov 02 '16 at 22:02
  • 3
    Or even shuffling an array from 1...90, then just looping through the array – RobotKarel314 Nov 02 '16 at 22:03
  • 1
    You've got only 90 different numbers, if the number of circles is larger than 90, eventually they have to repeat. – xiaofeng.li Nov 02 '16 at 22:03
  • Possible duplicate of [math random number without repeating a previous number](http://stackoverflow.com/questions/6625551/math-random-number-without-repeating-a-previous-number) – Heretic Monkey Nov 02 '16 at 22:06

5 Answers5

1

generate an array of length n (numberOfCircles, in your case) containing the integers [0..n], randomize it using lodash's .shuffle() function or similar, then use numbers from this array as needed:

var array = [];
for (var i = 0; i < numberOfCircles; i++) {
  array[i] = i;
}
array = _.shuffle(array);
for (var i = 0; i < numberOfCircles; i++) {
  randomNumber = array[i];
  // do more here
}
Dan O
  • 6,022
  • 2
  • 32
  • 50
0

One way to do it is to use a while loop to generate the random numbers, and keep an object of used values to check if the value has been used or not.

2 things that I think are worth mentioning here:

1) As others have mentioned, if you have more than 90 values, you must have duplicates

2) Usually when I do something like this, depending on what I'm trying to do, I create a threshhold for how many loop iterations I allow before moving forward. One example that jumps to mind is a random color generator that ensures that any two colors are "not too similar". After x number of loop iterations, though, I just use the color and move on so it does not lock down the browser and significantly impact performance. It really depends on what you're trying to do.

I will leave adding the tolerance and > 90 values as an exercise for you, but here is the basic idea:

function setUpEventHandlerForShowBallButton() {

  var myshowballbutton = document.getElementById('showball'); // local variable

  myshowballbutton.addEventListener('click', function() {

    // Generate a random number then draw a circle to display it
    // for loop not really needed if only displaying one ball
    var usedValues = {};
    var randomNumber;
    for (var i = 0; i < numberOfCircles; i++) {
      while (typeof randomNumber === "undefined" || typeof usedValues[randomNumber] !== "undefined") {
        randomNumber = Math.floor(Math.random() * 90 + 1);
      }
      usedValues[randomNumber] = randomNumber;
      drawCircle(myContext, circleCentreX, circleCentreY, circleRadius, circleColours[0], randomNumber);

      //circleCentreX += circleOffsetX;  // The adds the offset to the current x coord.
    }

  }, false);
}
mhodges
  • 10,938
  • 2
  • 28
  • 46
0

Did u try to take a variable to keep the previous randomNumber?

const previousNumber; //simple constant to store generated number

function setUpEventHandlerForShowBallButton() {

  var myshowballbutton = document.getElementById('showball');   // local variable

  myshowballbutton.addEventListener('click', function () {

    // Generate a random number then draw a circle to display it
    // for loop not really needed if only displaying one ball

    for (var i = 0; i < numberOfCircles; i++) {
    if(Math.floor(Math.random() * 90 + 1) !==previousNumber)
      {randomNumber = Math.floor(Math.random() * 90 + 1)}  
      previousNumber = randomNumber;

      drawCircle(myContext, circleCentreX, circleCentreY, circleRadius, circleColours[0], randomNumber);

      //circleCentreX += circleOffsetX;  // The adds the offset to the current x coord.
    }

  }, false);
}
Razvan Alex
  • 1,706
  • 2
  • 18
  • 21
0

You can create an array of numbers from 1 to 90, and then pick up a random number from 1 to 90 using it as index for extracting the corresponding number in the array

After that you recreate the array without the extracted number (or shift the position of the number in +1 offset), and than pick a new random number from 1 to 89 always as index

and so on, until you got one element in the array

But I think that the fastest way is to shuffle an array containing the number from 1 to 90 and then extract the numbers in a for cicle

I prefer the second method, and I don't think that using a dictionary for the extracted numbers is a good idea, because after some extraction you will get a lot of miss, leading in a slow execution

Nikaido
  • 4,443
  • 5
  • 30
  • 47
  • Shuffling an array in JavaScript is not necessarily efficient. And I don't understand your comment about using a dictionary? Checking to see if a property exists on an object is literally one operation. It doesn't loop through the properties and check them, like it would on an `array.indexOf()`.I think you have very limited knowledge of JavaScript - not entirely sure why you're answering this – mhodges Nov 02 '16 at 22:24
  • The problem is that when you have filled most of the number in the dictionary there is an high probability that the internal while will do more than one cicle And the problem would be worse with a range bigger than this – Nikaido Nov 02 '16 at 22:30
  • That I can agree with, which is why I mentioned it in my post – mhodges Nov 02 '16 at 22:34
0

The solution using self-invoked named anonymous local function and static variable:

function setUpEventHandlerForShowBallButton() {
    var myshowballbutton = document.getElementById('showball'),
        randomNumber;        

    // self-invoked named anonymous function
    (function getNumber(){
        randomNumber = Math.floor(Math.random() * 90 + 1);
        if (setUpEventHandlerForShowBallButton.numbers.indexOf(randomNumber) !== -1) {
            getNumber();
        }
    }())
    setUpEventHandlerForShowBallButton.numbers.push(randomNumber);

    myshowballbutton.addEventListener('click', function () {

        drawCircle(myContext, circleCentreX, circleCentreY, circleRadius, circleColours[0], randomNumber);

    }, false);
}
setUpEventHandlerForShowBallButton.numbers = [];  // static variable

setUpEventHandlerForShowBallButton();
RomanPerekhrest
  • 88,541
  • 4
  • 65
  • 105