Unicode of Life
ライフゲームで更新されるビットパターンをUnicodeのコードポイントとして文字列に変換
/**
* Copyright naraba ( http://wonderfl.net/user/naraba )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/smN1
*/
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.utils.Timer;
import flash.text.TextField;
import flash.text.TextFormat;
import com.bit101.components.Label;
import com.bit101.components.PushButton;
import com.bit101.components.InputText;
import com.bit101.components.ComboBox;
public class UnicodeOfLife extends Sprite
{
private const CHAR_SETS:Array = [
["ara", 0x0675, 0x06D5], ["kana", 0x30A1, 0x30FE],
["kabu", 0x3220, 0x3240], ["kilo", 0x3300, 0x3357],
["sqrk", 0x56D7, 0x571E], ["fish", 0x9B5A, 0x9C4F]
];
private const STATE_DEAD:uint = 0;
private const STATE_ALIVE:uint = 1;
private const FONT_SIZE:uint = 8;
private const CHAR_WIDTH:uint = 16;
private const STR_WIDTH:uint = 35;
private const SOUP_WIDTH:uint = CHAR_WIDTH * STR_WIDTH;
private const SOUP_HEIGHT:uint = 24;
private const COMP_WIDTH:uint = 40;
private const MSG_HOW2USE:String = "■これは\n" +
"ライフゲームで更新されるビットパターンを\nUnicodeのコードポイントとして文字列に変換するプログラム。\n\n" +
"■使い方\n" +
"Unicodeのコードポイント(16進数)で、文字セットの開始・終了を指定する。\n" +
"左側の入力ボックスに開始点を、右側の入力ボックスに終了点を入れて、\n" +
"startボタンを押す。stopしたあとstartすると再開。resetで初期化。\n\n" +
"条件: 開始点から終了点までにある文字数は1文字以上256文字以下。\n\n" +
"左上のコンボボックスからサンプルの文字セットを選んでもOK。\nサンプルの文字セット:\n" +
" ara, アラビアンな文字\n" +
" kana, カタカナ\n" +
" kabu, ㈱ みたいなやつ\n" +
" kilo, ㌔ みたいなやつ\n" +
" sqrk, 四角い漢字\n" +
" fish, さかな\n";
private const MSG_ERRSTART:String = "開始コードポイントが不正\n";
private const MSG_ERREND:String = "終了コードポイントが不正\n";
private var did_init:Boolean;
private var start_char:uint;
private var num_chars:uint;
private var soup:Array;
private var soup_swith:uint;
private var text:TextField;
private var timer:Timer;
private var button:PushButton;
private var reset:PushButton;
private var stbox:InputText;
private var enbox:InputText;
private var cbox:ComboBox;
public function UnicodeOfLife():void
{
text = new TextField();
var tf:TextFormat = new TextFormat(null, FONT_SIZE);
text.width = stage.stageWidth - 10;
text.height = stage.stageHeight - 80;
text.x = 5;
text.y = 50;
text.border = true;
addChild(text);
button = new PushButton(this, 0, 10, "start", toggle);
reset = new PushButton(this, 0, 10, "reset", init);
stbox = new InputText(this, 0, 12, "");
enbox = new InputText(this, 0, 12, "");
button.width = reset.width = stbox.width = enbox.width = COMP_WIDTH;
stbox.maxChars = enbox.maxChars = 4;
cbox = new ComboBox(this, 10, 10, "");
var stlab:Label = new Label(this, cbox.x + cbox.width + COMP_WIDTH / 2, 12, "U+");
stbox.x = stlab.x + stlab.width;
var enlab:Label = new Label(this, stbox.x + stbox.width, 12, " -- U+");
enbox.x = enlab.x + enlab.width;
button.x = enbox.x + enbox.width + COMP_WIDTH / 2;
reset.x = button.x + button.width + COMP_WIDTH / 2;
for (var i:uint; i < CHAR_SETS.length; i++) {
cbox.addItem(CHAR_SETS[i][0]);
}
cbox.addEventListener(Event.SELECT, choose);
cbox.selectedIndex = 0;
init(null);
timer = new Timer(200);
timer.addEventListener(TimerEvent.TIMER, update);
}
private function toggle(e:MouseEvent):void
{
if (timer.running) {
timer.stop();
reset.enabled = true;
button.label = "start";
} else {
var err:String = "";
if (did_init) {
var tmps:int = parseInt(stbox.text, 16);
var tmpn:int = parseInt(enbox.text, 16) - tmps + 1;
if (tmps < 0 || (tmps == 0 && stbox.text != "0")) { err += MSG_ERRSTART; }
if (tmpn < 1 || tmpn > 256 || enbox.text == "") { err += MSG_ERREND; }
start_char = tmps;
num_chars = tmpn;
}
if (err != "") {
text.text = "■エラー:\n" + err;
} else {
did_init = false;
reset.enabled = stbox.enabled = enbox.enabled = cbox.enabled = false;
timer.start();
button.label = "stop";
}
}
}
private function choose(e:Event):void
{
var b:ComboBox = e.currentTarget as ComboBox;
var idx:uint = b.selectedIndex;
stbox.text = CHAR_SETS[idx][1].toString(16).toUpperCase();
enbox.text = CHAR_SETS[idx][2].toString(16).toUpperCase();
}
private function init(e:Event):void
{
text.text = MSG_HOW2USE;
soup = new Array(2).map(function():* {
return new Array(SOUP_HEIGHT + 2).map(function():* {
return new Array(SOUP_WIDTH + 2).map(function():* {
return STATE_DEAD;
})
})
});
for (var y:uint = 1; y <= SOUP_HEIGHT; y++) {
for (var x:uint = 1; x <= SOUP_WIDTH; x++) {
soup[soup_swith][y][x] = Math.random() < 0.5 ? STATE_DEAD : STATE_ALIVE;
}
}
did_init = true;
stbox.enabled = enbox.enabled = cbox.enabled = true;
}
private function update(e:TimerEvent):void
{
text.text = soup_swith.toString();
var s:String = "";
var nbits:uint = 0;
var num:uint = 0;
var alv:uint;
for (var y:uint = 1; y <= SOUP_HEIGHT; y++) {
nbits = 0;
num = 0;
for (var x:uint = 1; x <= SOUP_WIDTH; x++) {
alv = 0;
if (soup[soup_swith][y - 1][x - 1] == STATE_ALIVE) alv++;
if (soup[soup_swith][y - 1][x ] == STATE_ALIVE) alv++;
if (soup[soup_swith][y - 1][x + 1] == STATE_ALIVE) alv++;
if (soup[soup_swith][y ][x - 1] == STATE_ALIVE) alv++;
if (soup[soup_swith][y ][x + 1] == STATE_ALIVE) alv++;
if (soup[soup_swith][y + 1][x - 1] == STATE_ALIVE) alv++;
if (soup[soup_swith][y + 1][x ] == STATE_ALIVE) alv++;
if (soup[soup_swith][y + 1][x + 1] == STATE_ALIVE) alv++;
if (alv == 3 || (alv == 2 && soup[soup_swith][y][x] == STATE_ALIVE)) {
soup[soup_swith ^ 1][y][x] = STATE_ALIVE;
} else {
soup[soup_swith ^ 1][y][x] = STATE_DEAD;
}
nbits++;
num = (num << 1) + soup[soup_swith ^ 1][y][x];
if (nbits >= CHAR_WIDTH) {
s += String.fromCharCode(start_char + (num % num_chars));
nbits = 0;
num = 0;
}
}
s += "\n";
}
soup_swith ^= 1;
text.text = s;
}
}
}