[朝ワン] MTDice
文字列からランダムな数値を作るテスト
MD5 で文字列をハッシュにして、適当な位置から文字を取得
MersenneTwister の seed に渡して、ランダムを生成する。
同じ文字列からは同じ値が取得される。
試しに文字列を変更して戻してみたりするといいと思うよ。
@author jc at bk-zen.com
/**
* 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);
}
}