challenge ラングトンのアリの描画

ラングトンのアリを描画してください。ラングトンのアリは、以下のような動きをする、セル・オートマトンです。(Wikipediaより引用)
- 黒いマスにアリがいた場合、90°右に方向転換し、そのマスの色を反転させ、1マス前進する。
- 白いマスにアリがいた場合、90°左に方向転換し、そのマスの色を反転させ、1マス前進する。
詳しくはWikipedia等で調べるか、参考ページに拙作のデモがありますのでご覧下さい。
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="ja">
<head>
       <meta http-equiv="content-type" content="text/html;charset=utf-8">
       <meta http-equiv="content-script-type" content="text/javascript">
       <meta http-equiv="content-style-type" content="text/css">
       <title>ラングトンの蟻</title>
<style type="text/css">
#canvas{
       border: 1px solid #999;
       width: 300px;
       height: 300px;
}
#canvas div{
       width: 3px;
       height: 3px;
       float: left;
}
</style>
<script>
var earth = [];
var WORLD_SIZE = 100;
var lang_ant;

function Ant(){}
Ant.prototype = {
    age : 0,
    ageDisplay : undefined,
    id : undefined,
    speed: 200,
    direction: [0,-1],//向き。x y軸。最初は上に動く
    position: [60,40],//初期位置
    world: [],
    start: function(){
        var self = this;
        this.id = setInterval(function(){self.move()}, 1000/this.speed);
    },
    move: function(){
        this.ageDisplay.innerHTML = ++this.age;
        this.moveNextCell();
        var cell = this.getCellInfo();
        var color = cell.getAndToggleColor();
        this.setNextDirection(color);
    },
    moveNextCell: function(){
        this.position[0] += this.direction[0];
        this.position[1] += this.direction[1];
        if(this.position[0] < 0 || this.position[1] < 0 ||
           this.position[0] >= WORLD_SIZE || this.position[1] >= WORLD_SIZE){
            clearInterval(this.id);
            this.die();
        }
    },
    getCellInfo: function(){
        var idx = this.position[0] + this.position[1] * WORLD_SIZE;
        return this.world[idx];
    },
    setNextDirection: function(bool){//colorがfalse(白)なら右へ、true(黒)なら左へ転回
        if(bool){//黒
            var tmp = this.direction[0];
            this.direction[0] = this.direction[1];
            this.direction[1] = -tmp;
        }
        else{//白
            var tmp = this.direction[0];
            this.direction[0] = -this.direction[1];
            this.direction[1] = tmp;
        }
    },
    die: function(){
        alert('Langton\'s ant is dead.');
        throw true;
    }
};

function Cell(elm){
    this.elm = elm;
}
Cell.prototype = {
    elm: undefined,
    color: false, //colorは2値なのでbooleanで表す
    colorList: ['#FFF','#000'],
    getAndToggleColor: function(){
        this.color = !this.color;
        var i = this.color ? 1 : 0;
        this.elm.style.backgroundColor = this.colorList[i];
        return !this.color;
    }
}
window.onload = function(){
    var canvas = document.getElementById('canvas');
    var div = '<div></div>';
    var inner_canvas = "";
    for(var i=0; i< WORLD_SIZE*WORLD_SIZE; i++){
        inner_canvas += div;
    }
    canvas.innerHTML = inner_canvas;
    
    var cells = canvas.childNodes;
    for(var i=0; i<cells.length; i++){//世界の誕生
        earth[i] = new Cell(cells[i]);
    }
    lang_ant = new Ant();//蟻の誕生
    lang_ant.world = earth;//地球に降り立つ
    lang_ant.ageDisplay = document.getElementById('step');
    
    document.getElementById('run').disabled = false;
}
</script>
</head>
<body>
<p><input type="button" value="run" onclick="lang_ant.start();this.disabled=true;" id="run" disabled="disabled"> <span id="step"></span>
 <input type="button" value="stop &amp; refresh" onclick="location.reload();"></p>
<div id="canvas"></div>

Posted feedbacks - ActionScript

ActionScriptで作成してみました。 30Frame/secでは遅かったので、1Frameに10Step進ませています。

ブラウザ上で確認できるようにwonderflにもおいておきます。

http://wonderfl.net/code/519de9f580e291a6309e2e8df3d5e8319a647433

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package {
    // Yet another implimentation of Langton's ant
    // This is made for "どう書く?org", http://ja.doukaku.org/276/
    // This code is written by xsd.
    import flash.display.Sprite;
    import flash.display.BitmapData;
    import flash.display.Bitmap;
    import flash.geom.Rectangle;
    import flash.events.Event;
    import flash.text.TextField;
    import flash.text.TextFormat;

    [SWF(width="465", height="465", backgroundColor="0xFFFFFF", frameRate="30")]
    public class LangtonsAnt extends Sprite {
    private const SCREEN_WIDTH:int = 465;
    private const SCREEN_HEIGHT:int = 465;
    private const CELL_SIZE:int = 4;
    private const STEP:int = 10;

    private var bm:BitmapData;
    private var bmp:Bitmap;
    private var tf:TextField;
    private var xAnt:int = 200;
    private var yAnt:int = 200;
    private var vx:int = 1;
    private var vy:int = 0;
    private var count:int = 0;
        
    public function LangtonsAnt():void {
            bm = new BitmapData(SCREEN_WIDTH, SCREEN_HEIGHT, false, 0xFFFFFF);
            bmp = new Bitmap(bm);
            this.addChild(bmp);

            tf = new TextField();
            tf.defaultTextFormat = new TextFormat("_Serif", 24, 0, true);
            tf.x = 0; tf.y = SCREEN_HEIGHT - 32; tf.width = SCREEN_HEIGHT; tf.height = 32;
            tf.selectable = false;
            this.addChild(tf);
            this.addEventListener(Event.ENTER_FRAME, update);
        }
        
        public function update(event:Event):void {
            bm.lock();
            var t:int, i:int;
    
            for (i = 0; i < STEP; i++) {
                xAnt += vx * CELL_SIZE;
                yAnt += vy * CELL_SIZE;
                var a:int = bm.getPixel(xAnt, yAnt);
                if (a == 0) {
                    bm.fillRect(new Rectangle(xAnt, yAnt, CELL_SIZE, CELL_SIZE), 0xFFFFFF);
                    t = vx; vx = vy; vy = -t;
                } else {
                    bm.fillRect(new Rectangle(xAnt, yAnt, CELL_SIZE, CELL_SIZE), 0x000000);
            t = vy; vy = vx; vx = -t;
                }
                bm.unlock();
                if (xAnt <= CELL_SIZE || xAnt >= SCREEN_WIDTH - CELL_SIZE ||
                    yAnt <= CELL_SIZE || yAnt >= SCREEN_HEIGHT - CELL_SIZE) {
                    this.removeEventListener(Event.ENTER_FRAME, update);
                    break;
                }
                count++;
                tf.text = "Step: "+count;
            }
        }
    }
}

Index

Feed

Other

Link

Pathtraq

loading...