In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

[朝ワン] MTDice

文字列からランダムな数値を作るテスト
MD5 で文字列をハッシュにして、適当な位置から文字を取得
MersenneTwister の seed に渡して、ランダムを生成する。
同じ文字列からは同じ値が取得される。
試しに文字列を変更して戻してみたりするといいと思うよ。

@author jc at bk-zen.com
Get Adobe Flash player
by bkzen 06 Jul 2009
/**
 * Copyright bkzen ( http://wonderfl.net/user/bkzen )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/wDJ6
 */

package  
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.text.TextField;
    import flash.text.TextFieldType;
    
    /**
     * 文字列からランダムな数値を作るテスト
     * MD5 で文字列をハッシュにして、適当な位置から文字を取得
     * MersenneTwister の seed に渡して、ランダムを生成する。
     * 同じ文字列からは同じ値が取得される。
     * 試しに文字列を変更して戻してみたりするといいと思うよ。
     * 
     * @author jc at bk-zen.com
     */
    public class MTTest extends Sprite
    {
        private var inputTxt:TextField;
        private var resultTxt:TextField;
        private var dice:MTDice;
        
        public function MTTest() 
        {
            dice = new MTDice("test");
            inputTxt = new TextField();
            inputTxt.type = TextFieldType.INPUT;
            inputTxt.border = true;
            inputTxt.height = 16;
            inputTxt.width = 100;
            inputTxt.text = "test";
            inputTxt.addEventListener(Event.CHANGE, onChange);
            addChild(inputTxt);
            resultTxt = new TextField();
            resultTxt.width = 465;
            resultTxt.height = 400;
            resultTxt.y = 16;
            addChild(resultTxt);
            onChange();
        }
        
        private function onChange(e:Event = null):void 
        {
            resultTxt.text = "";
            dice.changeSeed(inputTxt.text);
            for (var i: int = 0; i < 20; i++ )
            {
                resultTxt.appendText("rand : " + dice.random(0, 1) + "\n");
            }
        }
        
    }
    
}

/**
 * 文字列からランダムな数値を作る。
 */
class MTDice
{
    import com.adobe.crypto.MD5;
    private var seed:String;
    private var hash:String;
    private var _position: uint;
    private var mt: MersenneTwister;
    
    function MTDice(seed: Object, position: int = 20090706)
    {
        changeSeed(seed, position);
    }
    
    public function changeSeed(value: Object, position: int = 20090706): void
    {
        if (String(value) != seed) 
        {
            this.seed = String(value);
            hash = MD5.hash(this.seed);
        }
        this.position = position;
    }
    
    public function random(s: Number = 0, e: Number = 10): Number
    {
        return mt.nextNumber()*(e - s) + s;
    }
    
    public function get position():uint { return _position; }
    
    public function set position(value:uint):void 
    {
        _position = value;
        var s: int = value % 32, l: int = (value % 8) + 1, x: int = value % 99;
        var v: String = "";
        for (var i: int = 0; i < l;i++ )
        {
            v += hash.charAt(((s + i) * x) % 32);
        }
        mt = new MersenneTwister(parseInt(v, 16));
    }
}

/**
 * http://onegame.bona.jp/tips/mersennetwister.html
 */
class MersenneTwister
{
    private const N:int = 624;
    private const M:int = 397;
    private const UPPER_MASK:uint = 0x80000000;
    private const LOWER_MASK:uint = 0x7fffffff;
    private const MATRIX_A:uint   = 0x9908b0df;
    private var x:Array;
    private var p:int;
    private var q:int;
    private var r:int;
    
    public function MersenneTwister(s:uint) {
        x = new Array();
        seed = s;
    }
    
    public function set seed(s:uint):void {
        x[0] = s;
        for (var i:int = 1; i < N; i++) {
            x[i] = imul(1812433253, x[i - 1] ^ (x[i - 1] >>> 30)) + i;
            x[i] &= 0xffffffff;
        }
        p = 0;
        q = 1;
        r = M;
    }
    
    /**
     * [0, 1)
     */
    public function nextNumber():Number {
        return next(32) / 4294967296;
    }
    
    private function next(bits:int):uint {
        var y:uint = (x[p] & UPPER_MASK) | (x[q] & LOWER_MASK);
        x[p] = x[r] ^ (y >>> 1) ^ ((y & 1) * MATRIX_A);
        y = x[p];
        
        if (++p == N) {p = 0;}
        if (++q == N) {q = 0;}
        if (++r == N) {r = 0;}
        
        y ^= (y >>> 11);
        y ^= (y << 7) & 0x9d2c5680;
        y ^= (y << 15) & 0xefc60000;
        y ^= (y >>> 18);
        return y >>> (32 - bits);
    }

    private function imul(a:Number, b:Number):Number {
        var al:Number = a & 0xffff;
        var ah:Number = a >>> 16;
        var bl:Number = b & 0xffff;
        var bh:Number = b >>> 16;
        var ml:Number = al * bl;
        var mh:Number = ((((ml >>> 16) + al * bh) & 0xffff) + ah * bl) & 0xffff;
        
        return (mh << 16) | (ml & 0xffff);
    }
}