math random number without repeating a previous number

家住魔仙堡 提交于 2019-12-17 03:17:35

问题


Can't seem to find an answer to this, say I have this:

setInterval(function() {
    m = Math.floor(Math.random()*7);
    $('.foo:nth-of-type('+m+')').fadeIn(300);
}, 300);

How do I make it so that random number doesn't repeat itself. For example if the random number is 2, I don't want 2 to come out again.


回答1:


There are a number of ways you could achieve this.

Solution A: If the range of numbers isn't large (let's say less than 10), you could just keep track of the numbers you've already generated. Then if you generate a duplicate, discard it and generate another number.

Solution B: Pre-generate the random numbers, store them into an array and then go through the array. You could accomplish this by taking the numbers 1,2,...,n and then shuffle them.

shuffle = function(o) {
    for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
    return o;
};

var randorder = shuffle([0,1,2,3,4,5,6]);
var index = 0;

setInterval(function() {
    $('.foo:nth-of-type('+(randorder[index++])+')').fadeIn(300);
}, 300);

Solution C: Keep track of the numbers available in an array. Randomly pick a number. Remove number from said array.

var randnums = [0,1,2,3,4,5,6];

setInterval(function() {
    var m = Math.floor(Math.random()*randnums.length);
    $('.foo:nth-of-type('+(randnums[m])+')').fadeIn(300);
    randnums = randnums.splice(m,1);
}, 300);



回答2:


You seem to want a non-repeating random number from 0 to 6, so similar to tskuzzy's answer:

var getRand = (function() {
    var nums = [0,1,2,3,4,5,6];
    var current = [];
    function rand(n) {
        return (Math.random() * n)|0;
    }
    return function() {
      if (!current.length) current = nums.slice();
      return current.splice(rand(current.length), 1);
    }
}());

It will return the numbers 0 to 6 in random order. When each has been drawn once, it will start again.




回答3:


I like Neal's answer although this is begging for some recursion. Here it is in java, you'll still get the general idea. Note that you'll hit an infinite loop if you pull out more numbers than MAX, I could have fixed that but left it as is for clarity.

edit: saw neal added a while loop so that works great.

public class RandCheck {
    private List<Integer> numbers;
    private Random rand;
    private int MAX = 100;

    public RandCheck(){
        numbers = new ArrayList<Integer>();
        rand = new Random();
    }

    public int getRandomNum(){
        return getRandomNumRecursive(getRand());
    }

    private int getRandomNumRecursive(int num){
        if(numbers.contains(num)){
            return getRandomNumRecursive(getRand());
        } else {
            return num;
        }
    }

    private int getRand(){
        return rand.nextInt(MAX);
    }

    public static void main(String[] args){
        RandCheck randCheck = new RandCheck();

        for(int i = 0; i < 100; i++){
            System.out.println(randCheck.getRandomNum());
        }
    }
}



回答4:


could you try that,

setInterval(function() {
    m = Math.floor(Math.random()*7);
    $('.foo:nth-of-type(' + m + ')').fadeIn(300);
}, 300);



回答5:


Generally my approach is to make an array containing all of the possible values and to:

  1. Pick a random number <= the size of the array
  2. Remove the chosen element from the array
  3. Repeat steps 1-2 until the array is empty

The resulting set of numbers will contain all of your indices without repetition.

Even better, maybe something like this:

var numArray = [0,1,2,3,4,5,6];
numArray.shuffle();

Then just go through the items because shuffle will have randomized them and pop them off one at a time.




回答6:


not sure if its too late, but would still like to add--

var RecordKeeper = {};

SRandom = function () {
    currTimeStamp = new Date().getTime();
    if (RecordKeeper.hasOwnProperty(currTimeStamp)) {
        RecordKeeper[currTimeStamp] = RecordKeeper[currTimeStamp] + 1;
        return currTimeStamp.toString() + RecordKeeper[currTimeStamp];
    }
    else {
        RecordKeeper[currTimeStamp] = 1;
        return currTimeStamp.toString() + RecordKeeper[currTimeStamp];
    }
}

this basically uses timestamp (every millisecond) to always generate a unique number.




回答7:


Here's a simple fix, if a little rudimentary:

if(nextNum == lastNum){
    if (nextNum == 0){nextNum = 7;} 
    else {nextNum = nextNum-1;}
}

If the next number is the same as the last simply minus 1 unless the number is 0 (zero) and set it to any other number within your set (I chose 7, the highest index).

I used this method within the cycle function because the only stipulation on selecting a number was that is musn't be the same as the last one.

Not the most elegant or technically gifted solution, but it works :)




回答8:


Use sets. They were introduced to the specification in ES6. A set is a data structure that represents a collection of unique values, so it cannot include any duplicate values. I needed 6 random, non-repeatable numbers ranging from 1-49. I started with creating a longer set with around 30 digits (if the values repeat the set will have less elements), converted the set to array and then sliced it's first 6 elements. Easy peasy. Set.length is by default undefined and it's useless that's why it's easier to convert it to an array if you need specific length.

let randomSet = new Set();
for (let index = 0; index < 30; index++) {
        randomSet.add(Math.floor(Math.random() * 49) + 1) 
    };
let randomSetToArray = Array.from(randomSet).slice(0,6);
console.log(randomSet);
console.log(randomSetToArray);



回答9:


you can do this. Have a public array of keys that you have used and check against them with this function:

function in_array(needle, haystack)
{
    for(var key in haystack)
    {
        if(needle === haystack[key])
        {
            return true;
        }
    }

    return false;
}

(function from: javascript function inArray)

So what you can do is:

var done = [];
setInterval(function() {
    var m = null;
    while(m == null || in_array(m, done)){
       m = Math.floor(Math.random()*7);
    }
    done.push(m);
    $('.foo:nth-of-type('+m+')').fadeIn(300);
}, 300);

This code will get stuck after getting all seven numbers so you need to make sure it exists after it fins them all.



来源:https://stackoverflow.com/questions/6625551/math-random-number-without-repeating-a-previous-number

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!