ラングトンの蟻

 最近「ラングトンの蟻」というものを知ったので作ってみました。

 手順は簡単で、
1.アリは頭の向いてる方向に1マス進む
2.元いたマスは色が反転する
3.進んだ先のマスが白ならばアリは右に90度回転、黒なら左に90度回転する
f:id:pongeponge:20140227231703j:plain
4.手順1に戻る
5.満足したらやめる

これだけ。
やってみると、

f:id:pongeponge:20140227231704j:plain
最初はこんなん

f:id:pongeponge:20140227231705j:plain
ちょっと大きくなってきて

f:id:pongeponge:20140227231706j:plain
突然触手を伸ばし始めて

f:id:pongeponge:20140227231707j:plain
(上下左右でループしてるので)戻ってきてぶつかってまた触手伸ばしてをくりかえす


 まだ上下左右の4方向だから納得できるけど、斜め方向を加えた8方向になるとウニョウニョ度が激増して全体がアメーバみたいな動きするから気持ち悪い。

ソースコードは以下

Form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace RangtonNoAri
{
    public partial class Form1 : Form
    {
        public CMain cm;

        public Form1()
        {
            InitializeComponent();
            cm = new CMain();
            this.pictureBox1.Image = cm.world;
        }

        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            //e.Graphics.DrawImage(cm.world, new Point(0, 0));
        }

        private void button1_Click(object sender, EventArgs e)
        {
            this.timer1.Enabled = true;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            for (int i = 0; i < 50; i++)
            {
                cm.Step();
            }
            this.pictureBox1.Invalidate();
        }
    }
}

CMain.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace RangtonNoAri
{
    public class CMain
    {
        public Bitmap world;
        private Graphics g;
        CAnt ant;
        Point ws = new Point(400, 400);

        public CMain()
        {
            ant = new CAnt(ws);
            this.CrateWorld();
        }

        //1ステップ
        public void Step()
        {
            ant.ChangeDirection(this.GetColor(ant.p));
            this.ChangePixColor(ant.p);
            ant.Move();
            ant.p = this.Edge(ant.p);
        }

        //ビットマップ生成
        private void CrateWorld()
        {
            world = new Bitmap(ws.X, ws.Y);
            g = Graphics.FromImage(world);
            g.FillRectangle(Brushes.White, new RectangleF(0, 0, ws.X, ws.Y));
        }

        //指定場所の色取得
        private Color GetColor(Point p)
        {
            return world.GetPixel(p.X, p.Y);
        }

        //タイルの色変更
        private void ChangePixColor(Point p)
        {
            if (GetColor(p) == Color.FromArgb(255, 255, 255))
            {
                world.SetPixel(p.X, p.Y, Color.Black);
            }
            else if (GetColor(p) == Color.FromArgb(0, 0, 0))
            {
                world.SetPixel(p.X, p.Y, Color.White);
            }
        }

        //境界
        private Point Edge(Point p)
        {
            if (p.Y < 0) p.Y = ws.Y + p.Y;
            if (p.Y >= ws.Y) p.Y = p.Y % ws.Y;
            if (p.X < 0) p.X = ws.X + p.X;
            if (p.X >= ws.X) p.X = p.X % ws.X;

            return p;
        }
    }

    class CAnt
    {
        public Point p;
        private int d;

        public CAnt(Point ws)
        {
            p = new Point(ws.X/2, ws.Y/2);
            d = 1;
        }
        
        //方向
        public void ChangeDirection(Color c)
        {
            if (c == Color.FromArgb(255,255,255)) d+=1;
            else if (c == Color.FromArgb(0, 0, 0)) d-=1;

            if (d < 0) d = 4+d;
            if (d > 3) d = d-4;
        }

        //移動
        public void Move()
        {  
            switch (d)
            {
                case 0:
                    p.Y--;  //上
                    break;
                case 1:
                    p.X++;  //右
                    break;
                case 2:
                    p.Y++;  //下
                    break;
                case 3:
                    p.X--;  //左
                    break;
            }
        }        
    }
}


ラングトンのアリ - Wikipedia
働かないアリに意義がある (メディアファクトリー新書)