Generate Random Number Using math.random, But Without Repeats

279 Views Asked by At

For a yearly Christmas event for an organization I'm a part of, we usually hold a raffle where people have the opportunity to win free prizes by just attending and getting a number ticket at the door. We use a program written in Flash (Using ActionScript 2.0) that selects a random number utilizing math.random, with some parameters attached to it, as shown below:

//maxNr = 999999999999999;


initRandom = function(){
    var nr = Math.ceil(Math.ceil(Math.random()*(maxNr));
    var nrString = "";
    for( var j=0; j<(maxNr.toString().length-nr.toString().length); j++){
        nrString += "0";
    }
    nrString += nr.toString();
    var holder = this.createEmptyMovieClip("holder",1);
    for( i=0; i<maxNr.toString().length; i++ ){
        var mc = holder.attachMovie("number","n"+i,i+10);
        mc._x = i*350;
        mc.anim_mc.gotoAndPlay( Math.floor(Math.random()*9) + 1 );
        this["iv"+i] = setInterval( this, "revealNumber", 2000 + (500*i), nrString.substr(i,1), i );
    }
    // scale (if needed) and center
    if( holder._width > Stage.width ){
        holder._width = Stage.width;
        holder._yscale = holder._xscale;
    }
    holder._x = Stage.width/2 - holder._width/2;
    holder._y = 100;
    // buttons
    back_btn.onRelease = function(){
        for(item in holder){
            holder[item].removeMovieClip();
        }
        gotoAndStop("intro");
    }
}

revealNumber = function( digit, i ){
    clearInterval( this["iv"+i] );
    holder["n"+i].gotoAndStop("done");
    holder["n"+i]["number_txt"].text = digit;
}

initRandom();

stop();

It's meant to return a random number between 1 and 1000, as defined by:

go_btn.onRelease = function(){
    maxNr = Math.max( 1000 , 1 );
    gotoAndStop("random");
}

stop();

It was written by a member of our organization who unfortunately passed away during the year, and I have little to no programming knowledge but I am a quick learner and have actually modified some of the code to get to the point it is currently. However, I'm trying to add in a parameter that would disallow the function from repeating a number, ie, excluding an already generated number from being reselected. I've spent days scouring any resource possible and have only met dead ends.

With the approach currently taken, is it possible to add in this parameter to this existing code, and how can I go about doing that?

Any help, suggestion or reply would be very greatly appreciated!

2

There are 2 best solutions below

2
Organis On

My AS2 is a bit rusty, but I think the following script explains the general idea. You need some registry to record generated numbers so you can skip them next time you generate one. I used the _global object so that this logic transcends even multiple instances of the following script.

// Create an Array to record generated numbers.
// The _global object is always present and can be accessed from anywhere.
if (_global.uniqueNr == undefined)
{
    _global.uniqueNr = [];
}

function initRandom()
{
    var nr;

    do
    {
        nr = Math.ceil(Math.ceil(Math.random()*(maxNr));
    }
    while (_global.uniqueNr[nr] == true);
    
    // Record the newly generated number so it would never drop again.
    _global.uniqueNr[nr] = true;
    
    // At this point you can be sure that "nr" contains a unique value.
0
Yoones Mashayekhi On
package 
{
    public class RandomGenerator
    {
        private var _st:Number;
        private var _en:Number;
        private var _len:Number;
        private var _pos:Number;
        private var _numPos:Number;
        private var _myNums:Array;
        private var _randNums:Array;
            
        public function RandomGenerator(en:Number, st:Number = 0) 
        {
            _st = st;
            _en = en;
            
            // just in case if params order mixup:
            if(en < st){
                _st = en;
                _en = st;
            }
            
            _len = _en - _st + 1;
            shuffle();
        }
        
        public function getNum():Number
        {
            // if passed last item:
            if(_numPos == _len)shuffle();
            
            var myResult:Number = _randNums[_numPos];
            _numPos++;
            return myResult;
        }
        
        private function shuffle():void
        {
            _numPos = 0;
            _randNums = [];
            _myNums = [];
            
            // Creating Numbers Array:
            var i:Number;
            for(i = 0; i<_len; i++){ _myNums[i] = _st + i; }
            
            // Creating shuffled Numbers Array:
            i = 0;
            while(_myNums.length > 0){
                _pos = Math.round(Math.random()*(_myNums.length-1));
                _randNums[i] = _myNums[_pos];
                i++;
                _myNums.splice(_pos,1);
            }
        }
        
        public function get len():Number
        {
            return _len;
        }

    }
    
}

make an object from this class for example cardGenerator:RandomGenerator = new RandomGenerator(51, 0) and finally you can get random number without repeat with this codes:

for (var i:int = 0; i < cardGenerator.len; i++) {
     trace(cardGenerator.getNum());               
}