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 - Scala

Scalaで。春っぽい雰囲気にしてみました!?(季節を無視して)。ScalaどころかSwingアプリとしても拙い作りかもしれません。。。 paintComponent内で結構ぐるぐる回してもいけるもんなんですね。もしかしたら、マシンパワーによっては表示が追いつかないのかもしれません。

 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
import scala.collection.mutable.ListBuffer
import scala.concurrent.ops._
import scala.swing._
import scala.util._
import java.awt.{Graphics, Dimension}

trait AntWorld {
    protected val w:Int
    protected val h:Int
    protected def reflect
     var ants:List[Ant] = Nil
    lazy val table:List[Array[Int]] = List.tabulate(w, {_=>Array.make(h,0)})
    private val r = new Random()
    def ant(c:Int) = new Ant(r.nextInt(w)/2+w/4, r.nextInt(h)/2+h/4, c)
    def antStart() = {
        spawn {
            while(true) {
                ants.foreach {_.move}
                reflect
                Thread.sleep(1)
            }
        }
    }
    class Ant(var x:Int, var y:Int, c:Int) {
        private val rads = List((0,-1), (1,0), (0,1), (-1,0))
        private val (initX, initY) = (x, y)
        private var radi = 0
        def init = { x = initX; y = initY; radi = 0 }
        def move = {
            val v = table(x)(y)
            table(x)(y) = (if (v != 0) 0 else c)
            radi = (radi + (if (v != 0) 1 else 3) ) % 4
            x = (x + rads(radi)._1 + w) % w
            y = (y + rads(radi)._2 + h) % h
        }
    }
}

object LangtonAnt extends SimpleGUIApplication {
    import java.awt.Color
    val aSize = 5
    def top = new MainFrame {
        title = "Langton's Ant"
        val panel = new Panel() with AntWorld {
            def reflect = repaint
            val (w, h) = (100, 100)
            peer.setPreferredSize(new Dimension(w * aSize, h * aSize))
            override def paintComponent(g:Graphics) = {
                super.paintComponent(g)
                for (x <- 0 until w; y <- 0 until h) {
                    table(x)(y) match {
                        case 0 => g.setColor(Color.WHITE)
                        case c => g.setColor(new Color(c))
                    }
                    g.fillRect(x * aSize, y * aSize, aSize, aSize)
                }
            }
            def clear = {
                table.foreach { a => for (i <- 0 until a.length) a(i) = 0 }
            }
            def reset = {
                ants =
                    ant(Color.GREEN.getRGB) ::
                    ant(Color.PINK.getRGB) ::
                    ant(Color.BLUE.getRGB) ::
                    ant(Color.RED.getRGB) ::
                    ant(Color.CYAN.getRGB) ::
                    Nil
                clear
            }
            def replay = {
                this.synchronized {
                    ants.foreach( _.init )
                    clear
                }
            }
            reset
        }
        contents = new BoxPanel(Orientation.Vertical ) {
            contents += new BoxPanel(Orientation.Horizontal ) {
                contents += new Button(Action("Clear"){ panel.clear })
                contents += new Button(Action("Replay"){ panel.replay })
                contents += new Button(Action("Reset"){ panel.reset })
            }
            contents += panel
        }
        panel.antStart
    }
}

Index

Feed

Other

Link

Pathtraq

loading...