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); } } [朝ワン] MTDice