【问题标题】:How to generate 4 random non-repeating numbers from 0-9?如何从 0-9 生成 4 个随机非重复数字?
【发布时间】:2017-02-25 11:09:47
【问题描述】:

我想从 0-9 中获取一个随机数字并将其弹出以使其不会重复,但我发现在第二个数字被按下后它并没有弹出它的数字。相反,会弹出一些尚未选择的其他数字,从而为重复提供空间。

var yourNum = [],
  oppNum = [],
  choose = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

function chooseRandomNumber() {
  return choose[Math.floor(Math.random() * choose.length)];
}

for (var i = 0; i < 4; i++) {
  if (i === 0) {
    yourNum.push(chooseRandomNumber());
    if (yourNum[yourNum.length - 1] === 9) {
      choose.pop();
    } else {
      choose.splice(yourNum[0], 1);
    }
  } else if (i === 1) {
    yourNum.push(chooseRandomNumber());
    if (yourNum[yourNum.length - 1] === 9) {
      choose.pop();
    } else {
      choose.splice(yourNum[1], 1);
    }
  } else if (i === 2) {
    yourNum.push(chooseRandomNumber());
    if (yourNum[yourNum.length - 1] === 9) {
      choose.pop();
    } else {
      choose.splice(yourNum[2], 1);
    }
  } else if (i === 3) {
    yourNum.push(chooseRandomNumber());
    if (yourNum[yourNum.length - 1] === 9) {
      choose.pop();
    } else {
      choose.splice(yourNum[3], 1);
    }
  }
}

console.log(choose);
console.log(yourNum);

【问题讨论】:

  • 请同时添加一个可能的结果。

标签: javascript random


【解决方案1】:

function getRand(min, max, result) {
  result = result || [];
  
  if(result.length == 4) {
    return result;
  }
  
  var rand =  Math.floor(Math.random()*max) + min;
  
  if(result.indexOf(rand) === -1) {
    result.push(rand);
  }
  return getRand(min, max, result);
}

var result = getRand(1,9);
console.log(result);

【讨论】:

    【解决方案2】:

    您的整个方法过于复杂且性能不佳。

    更好的方法:

    //first we need a shuffle function
    function shuffle(array){
        for(var i = array.length, j, tmp; i--; ){
            j = 0|(Math.random() * i);
            tmp = array[j];
            array[j] = array[i];
            array[i] = tmp;
        }
        return array;
    }
    
    //now let's define a sequence of possible values
    var numset = [0,1,2,3,4,5,6,7,8,9];
    
    //shuffle the sequence and take the first 4 values 
    var fourRandomValues = shuffle(numset).slice(0,4);
    console.log("four random values: " + fourRandomValues);
    
    //doing this multiple times:
    for(var values = []; values.length < 10;){
        //shuffle again, and take the values that are now at the beginning of this sequence
        values.push( shuffle(numset).slice(0,4) );
    }
    console.log("more random values: \n" + values.join("\n"));

    编辑:

    为了通过实现某种迭代器来解决holi-java的方法,我将添加一种使用 ES6 迭代器/生成器的方法

    由于生成器可以是无限的序列,我们需要考虑这一点。我们通过缓冲有限数量的值并随机返回它们来做到这一点;基本上是一个混洗值的移动框架。

    function *shuffled(iterable, bufferSize = 256){
        var buffer, numValues = 0, randomIndex;
        if(Array.isArray(iterable) && iterable.length <= bufferSize){
            //an optimization for (small) Arrays:
            buffer = iterable.slice();
            numValues = iterable.length;
        }else{
            buffer = Array( bufferSize )
            for(var value of iterable){
                //push value from the iterable to the buffer
                buffer[numValues++] = value;
                
                //buffer is full, yield a random value
                if(numValues === bufferSize){
                    //choose a random value from the buffer
                    randomIndex = 0|(Math.random() * (numValues-1));
                    //yield it
                    yield buffer[randomIndex];
                    
                    //overwrite the value with the last index 
                    //that's cheaper than pop() and splice()
                    buffer[randomIndex] = buffer[--numValues];
                }
            }
        }
        //iterable doesn't provide any more values
        //flush the buffer in a random order
        while(numValues){
            randomIndex = 0|(Math.random() * (numValues-1));
            yield buffer[randomIndex];
            buffer[randomIndex] = buffer[--numValues];
        }
    }
    
    //every Array is a valid iterator
    for(var v of shuffled([0,1,2,3,4,5,6,7,8,9])) 
        console.log(v);

    这样我们就可以打乱一个值流,而无需先缓存数组中的所有值。

    • 专业版:内存高效
    • 可能的问题:如果缓冲区太小,则结果不再感觉随机,因为在序列后期生成的值根本无法完全转移到开头。您会看到一些噪音,但感觉不再是随机的了。

    现在让我们跳入潜在的无限序列:

    // *shuffled again, for this snippet
    function *shuffled(iterable, bufferSize = 256){
        var buffer, numValues = 0, randomIndex;
        if(Array.isArray(iterable) && iterable.length <= bufferSize){
            buffer = iterable.slice();
            numValues = iterable.length;
        }else{
            buffer = Array( bufferSize )
            for(var value of iterable){
                buffer[numValues++] = value;
                if(numValues === bufferSize){
                    randomIndex = 0|(Math.random() * (numValues-1));
                    yield buffer[randomIndex];
                    buffer[randomIndex] = buffer[--numValues];
                }
            }
        }
        while(numValues){
            randomIndex = 0|(Math.random() * (numValues-1));
            yield buffer[randomIndex];
            buffer[randomIndex] = buffer[--numValues];
        }
    }
    
    //creates an infinite sequence of numbers
    function *count(){
        for(var index = 0; true;)
            yield index++;
    }
    
    //like limits a iterator but for iterators
    function *take(n, iterator){
        for(var value of iterator){
            if(n-- > 0) yield value;
            else break;
        }
    }
    
    //create an (infinite) counter and convert it into a generator of shuffled values
    //with a bufferSize of 256 entries (play a bit with that value)
    var shuffledSequence = shuffled(count(), 256);
    //to convert that into an Array we take the first 1000 values generated from that generator
    var array = [...take(1000, shuffledSequence)];
    //and log it
    console.log(array.toString());

    【讨论】:

      【解决方案3】:

      下面这样是什么意思:

      function next() {
      function all() {
          return [].concat(Array(10).fill(null).map(function (_, index) {
              return index;
          }));
      }
      function random(start, end) {
          return parseInt(Math.random() * (end + 1 - start)) + start;
      }
      var self = this;
      
      self.all = self.all && self.all.length && self.all || all().sort(function(){
          return random(-1, 1);
      });
      return self.all.shift();}
      var results=Array(4).fill(null).map(next);
      console.log(results);
      

      【讨论】:

        【解决方案4】:

        我是这样更好地运行浏览器。

        var it = {
            next: function () {
                var self = this;
                self._all = self._all && self._all.length && self._all || self.shuffle(self.all());
        
                return self._all.shift();
            },
            all: function () {
                return [0,1,2,3,4,5,6,7,8,9];
            },
            random: function (start, end) {
                if (!end && end != 0) {
                    end = start;
                    start = 0;
                }
                return parseInt(Math.random() * (end + 1 - start)) + start;
            },
            shuffle: function (array) {
                var self = this;
                for (var i = array.length - 1; i > 0; --i) {
                    self.swap(array, i, self.random(i));
                }
                return array;
            },
            swap: function (array, i, j) {
                var tmp = array[i];
                array[i] = array[j];
                array[j] = tmp;
            },
            reset: function () {
                this._all = null;
            }
        };
        for (var i = 0; i < 10; i++) {
            var results=[];
            for(var n=0;n<4;n++) results.push(it.next());
            console.log("retain:"+it._all + '>>generated:' + results);
            it.reset();
        }

        【讨论】:

        【解决方案5】:

        编辑

        choose 数组中取出四个唯一数字。这就是你所追求的吗?

        var yourNum = [],
          oppNum = [],
          choose = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
        
        function chooseRandomNumber() {
          return choose[Math.floor(Math.random() * choose.length)];
        }
        
        var rand;
        for (var i = 0; i < 4; i++) {
          rand = chooseRandomNumber();
          yourNum.push(rand);
          choose.splice(choose.indexOf(rand), 1);
        }
        
        console.log(choose);
        console.log(yourNum);

        旧方法:

        var start = 0, end = 9;
        
        function generate(count) {
          var nums = [],
            random;
        
          for (var i = 0; i < count; i++) {
            while (!random || nums.indexOf(random) !== -1) {
              random = Math.floor(Math.random() * (end + 1)) + start;
            }
        
            nums.push(random);
          }
          
          return nums;
        }
        
        console.log(
          generate(4)
        );

        【讨论】:

          【解决方案6】:

          演示:

          function getRandomInt(min, max) {
            min = Math.ceil(min);
            max = Math.floor(max);
            return Math.floor(Math.random() * (max - min)) + min;
          }
          
          var yourNums = [];
          var choose = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
          
          for (var i = 0; i < 4; i++) {
            yourNums = yourNums.concat(choose.splice(getRandomInt(0, choose.length), 1))
          }
          
          console.log("yourNums is:")
          console.log(yourNums);
          console.log("===")
          console.log("choose is:")
          console.log(choose);

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-11-10
            • 1970-01-01
            • 2017-05-28
            • 1970-01-01
            • 2011-11-24
            • 2013-04-06
            相关资源
            最近更新 更多