C Sharp Programming

提供:kuhalaboWiki
移動: 案内, 検索

Visual Studio C#を使用した描画プログラムの作成


目次

プロパティの変更

ラベルの変更
label1.Text = "おはよう";
label1.BackColor = Color.FromArgb(100,0,255,0);

乱数の使用

サイコロ
Random saikoro = new Random();
label2.Text = saikoro.Next(1, 7).ToString();

Timerの使用

ルーレット
  • Timerのスタートとストップのトグルボタン
if (timer1.Enabled == true)
{
  timer1.Stop();
}
else
{
  timer1.Start();
}
  • timer1_Tick()メソッドの処理。Interval時間間隔ごとにテキストボックスから得た数字を最大値として乱数を発生させる。
Random roulette = new Random();
int kazu_max = int.Parse(textBox1.Text);
label2.Text = roulette.Next(1, kazu_max).ToString();


幾何学模様描画例

描画例のソース

exeプログラム例 直線,矩形,円弧,多角形,曲線など

線の描画

  • pictureboxを作成
  • Graphic gの作成
  • Penの作成
  • g.Draw系のメソッドで線を描画
g.DrawLine (pen, x1, y1, x2, y2)
(x1,y1)と(x2,y2)を結ぶ直線を描画する。
g.DrawRectangle (pen, x, y, w, h)
(x,y)を左上頂点とする幅w、高さhで指定された四角形を描画する。
g.DrawEllipse (pen, x, y, w, h)
(x,y)を左上頂点とする幅w、高さhで指定された四角形に内接する楕円を描画する。

以下のライブラリーをインポートしておく。

using System.Drawing.Drawing2D;

直線、矩形などの描画の基礎

        private void button1_Click(object sender, EventArgs e)
        {
            Graphics g = pictureBox1.CreateGraphics();
            Pen pen = new Pen(Color.Black);  //黒のペンを定義
            Pen boldPen = new Pen(Color.Black, 5); // 太いペン
            Pen dotPen = new Pen(Color.Black, 5); // 点線
            dotPen.DashStyle = DashStyle.Dot; 

            g.DrawLine(pen, 0, 10, 300, 10);
            g.DrawLine(boldPen, 0, 30, 300, 30);// 太い線
            g.DrawLine(dotPen, 0, 60, 300, 60);// 点線
            //点線パターンの変更
            dotPen.DashStyle = DashStyle.DashDot;
            g.DrawLine(dotPen, 0, 90, 300, 90);
            dotPen.DashStyle = DashStyle.DashDotDot;
            g.DrawLine(dotPen, 0, 120, pictureBox1.Width, 120);
            pen.Color = Color.Red; //ペンの色変更
            g.DrawLine(pen, 0, 150, pictureBox1.Width, 150);
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Graphics g = pictureBox1.CreateGraphics();
            Pen pen = new Pen(Color.Black);  //黒のペンを定義
            SolidBrush brush = new SolidBrush(Color.Black);//黒のブラシを定義
            // 枠の四角形を描画する
            g.DrawRectangle(pen, 0, 0, 100, 100);
            // 塗り潰しの四角形を描画する
            g.FillRectangle(brush, 50, 50, 100, 100);
            brush.Color = Color.Red;
            g.FillRectangle(brush, 150, 150, 200, 100);
        }

        private void button3_Click(object sender, EventArgs e)
        {
            Graphics g = pictureBox1.CreateGraphics();
            Pen pen = new Pen(Color.Black);
            SolidBrush brush = new SolidBrush(Color.Black);
            // 円を描画する
            g.DrawEllipse(pen, 0, 0, 100, 100);
            // 楕円を描画する
            g.DrawEllipse(pen, 0, 0, 200, 100);
            // 円弧を描画する
            g.DrawArc(pen, 200, 300, 150, 100, 10, 30);
            // 扇形を描画する
            g.DrawPie(pen, 300, 300, 200, 100, 10, 30);
            // 塗り潰した円を描画する
            g.FillEllipse(brush, 50, 50, 100, 100);
            // 作成したBrushオブジェクトを指定する
            TextureBrush br = new TextureBrush(Properties.Resources.book);
            g.FillEllipse(br, 100, 100, 100, 100);

        }

        private void button4_Click(object sender, EventArgs e)
        {
            Graphics g = pictureBox1.CreateGraphics();
            Pen pen = new Pen(Color.Black);

            // 折れ線を描画する
            Point[] points = new Point[4];
            points[0] = new Point(50, 0);
            points[1] = new Point(100, 50);
            points[2] = new Point(50, 100);
            points[3] = new Point(0, 50);
            g.DrawLines(pen, points);
            // 閉じた多角形を描画する
            points[0] = new Point(100, 0);
            points[1] = new Point(150, 50);
            points[2] = new Point(100, 100);
            points[3] = new Point(50, 50);
            pen.Color = Color.Red; //ペンの色変更
            g.DrawPolygon(pen, points);
        }

        private void button7_Click(object sender, EventArgs e)
        {
            Graphics g = pictureBox1.CreateGraphics();
            Pen pen = new Pen(Color.Black);

            Point[] points = new Point[4];
            // 曲線を描画する
            points[0] = new Point(20, 20);
            points[1] = new Point(100, 200);
            points[2] = new Point(200, 0);
            points[3] = new Point(300, 200);
            g.DrawLines(pen, points);
            //ヴェジェ
            g.DrawBeziers(pen, points);
            //スプライン
            g.DrawCurve(pen, points);
            g.DrawCurve(pen, points, 0F);
            g.DrawCurve(pen, points, 0.5F);
            g.DrawCurve(pen, points, 1F);
            g.DrawCurve(pen, points, 1.5F);
            g.DrawCurve(pen, points, 2F);
        }

描画領域のクリア

g.Clear(Color.White); //描画領域をクリア(白で塗りつぶす)

グラデーション

Graphics g = pictureBox1.CreateGraphics();
// グラデーションのペンを作成
Brush br = new LinearGradientBrush(new Point(0, 0), new Point(0, pictureBox1.Height), Color.Green, Color.White);
// グラデーションで塗り潰し
g.FillRectangle(br, 0, 0, pictureBox1.Width, pictureBox1.Height);

マウスムーブを使った描画

プロパティウィンドウにイベント(稲妻のアイコン)のリストを表示させ、MouseMoveイベントをダブルクリックすると、MouseMoveのメソッドが自動生成されます。

private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
  Graphics g = pictureBox1.CreateGraphics();
  Pen pen = new Pen(Color.Black);
  Random rndcolor = new Random();
  //描画色の決定
  int aa = rndcolor.Next(0, 256);
  int rr = rndcolor.Next(0, 256);
  int gg = 255 - e.X * 255 / pictureBox1.Width;
  int bb = e.Y * 255 / pictureBox1.Height;
  pen.Color = Color.FromArgb(aa, rr, gg, bb);
  // マウス位置へ直線を描画する
  g.DrawLine(pen, 0, 0, e.X, e.Y);
  g.DrawLine(pen, 0, pictureBox1.Height, e.X, e.Y);
  g.DrawLine(pen, pictureBox1.Width, 0, e.X, e.Y);
  g.DrawLine(pen, pictureBox1.Width, pictureBox1.Height, e.X, e.Y);
  label3.Text = e.X.ToString();
  label4.Text = e.Y.ToString();
}

forループを使った描画

  Graphics g = pictureBox1.CreateGraphics();

// 直線をループで描画する
  Pen pen = new Pen(Color.Black);
  Random rnd = new Random();
  for (int i = 0; i < pictureBox1.Width; i++)
  {
    int aa = rnd.Next(0, 256);
    int rr = rnd.Next(0, 256);
    int gg = rnd.Next(0, 256);
    int bb = rnd.Next(0, 256);
    pen.Color = Color.FromArgb(aa, rr, gg, bb);
    g.DrawLine(pen, pictureBox1.Width / 2, 0, i, pictureBox1.Height);
  }

// 点をループで描画する
  SolidBrush brush = new SolidBrush(Color.Black);
  Random rnd = new Random();
  int imax = 10000;
  for (int i = 0; i < imax; i++)
  {
    int aa = rnd.Next(0, 256);
    int rr = rnd.Next(0, 256);
    int gg = rnd.Next(0, 256);
    int bb = rnd.Next(0, 256);
    int xx = rnd.Next(0, pictureBox1.Width);
    int yy = rnd.Next(0, pictureBox1.Height);
    pen.Color = Color.FromArgb(aa, rr, gg, bb);
    brush.Color = Color.FromArgb(aa, rr, gg, bb);
    g.DrawRectangle(pen, xx, yy, 5, 5);
    g.FillRectangle(brush, xx, yy, 5, 5);
  }

// 円をループで描画する
    double pi = 3.14159;
   int x3 = pictureBox1.Width / 2;
   int y3 = pictureBox1.Height / 2;
   int r1 = 100, r2 = 50;
   int kkizami = 100;
   int shukai = 1;
   int n = 5;
   for (int i = 0; i < kkizami * shukai; i++)
   {
     double k = 2 * pi / kkizami * i;
     double x = x3 + r1 * Math.Cos(k);
     double y = y3 - r1 * Math.Sin(k);
     g.DrawEllipse(pen, (int)x - r2, (int)y - r2, 2 * r2, 2 * r2);
   }

アルキメデスの渦巻き

Graphics g = pictureBox1.CreateGraphics();
Pen pen = new Pen(Color.Black);
double pi = 3.14159;
int x3 = pictureBox1.Width / 2;
int y3 = pictureBox1.Height / 2;
double r1;
int kkizami = 1000;
int shukai = 100;
double n = 2;
double k,x=0,y=0,nx=0,ny=0;
nx = x3; ny = y3;
for (int i = 0; i < kkizami * shukai; i++)
{
  k = 2 * pi / kkizami * i;
  r1 = n * k;
  x = nx;
  y = ny;
  nx = x3 + r1 * Math.Cos(k);
  ny = y3 - r1 * Math.Sin(k);
  g.DrawLine(pen, (int)x, (int)y, (int)nx, (int)ny);
}

フェルマーの渦巻き

Graphics g = pictureBox1.CreateGraphics();
Pen pen = new Pen(Color.Black);
double pi = 3.14159;
int x3 = pictureBox1.Width / 2;
int y3 = pictureBox1.Height / 2;
double r1;
int kkizami = 100;
int shukai = 100;
double n = 10;
double k, x = 0, y = 0, nx = 0, ny = 0;
nx = x3; ny = y3;
for (int i = 0; i < kkizami * shukai; i++)
{
  k = 2 * pi / kkizami * i;
  r1 = n * Math.Sqrt(k);
  x = nx;
  y = ny;
  nx = x3 + r1 * Math.Cos(k);
  ny = y3 - r1 * Math.Sin(k);
  g.DrawLine(pen, (int)x, (int)y, (int)nx, (int)ny);
}

正葉曲線:単

Graphics g = pictureBox1.CreateGraphics();
Pen pen = new Pen(Color.Black);
double pi = 3.14159;
int x3 = pictureBox1.Width / 2;
int y3 = pictureBox1.Height / 2;
double r1;
int kkizami = 1000;
int shukai = 1;
double n = 5,m=100;
double k, x = 0, y = 0, nx = 0, ny = 0;
nx = x3; ny = y3;
for (int i = 0; i < kkizami * shukai; i++)
{
  k = 2 * pi / kkizami * i;
  r1 = m * Math.Abs(Math.Sin(n * k));
  x = nx;
  y = ny;
  nx = x3 + r1 * Math.Cos(k);
  ny = y3 - r1 * Math.Sin(k);
  g.DrawLine(pen, (int)x, (int)y, (int)nx, (int)ny);
}

正葉曲線:複

Graphics g = pictureBox1.CreateGraphics();
Pen pen = new Pen(Color.Black);
double pi = 3.14159;
int x3 = pictureBox1.Width / 2;
int y3 = pictureBox1.Height / 2;
double r1;
int kkizami = 1000;
int shukai = 1;
double n = 5, m = 20;
double k, x = 0, y = 0, nx = 0, ny = 0;
nx = x3; ny = y3;
for (int i = 0; i < kkizami * shukai; i++)
{
  k = 2 * pi / kkizami * i;
  r1 = m * Math.Abs( 7* Math.Sin(n * k) + 1 * Math.Sin(3 * n * k) + 1 * Math.Sin(5 * n * k ));
  x = nx;
  y = ny;
  nx = x3 + r1 * Math.Cos(k);
  ny = y3 - r1 * Math.Sin(k);
  g.DrawLine(pen, (int)x, (int)y, (int)nx, (int)ny);
}

外サイクロイド

Graphics g = pictureBox1.CreateGraphics();
Pen pen = new Pen(Color.Black);
double pi = 3.14159;
int x3 = pictureBox1.Width / 2;
int y3 = pictureBox1.Height / 2;
double r1;
int kkizami = 100;
int shukai = 50;
double a = 100, b = 65;
double k, x = 0, y = 0, nx = 0, ny = 0;
nx = x3 + a; ny = y3;
for (int i = 0; i < kkizami * shukai; i++)
{
  k = 2 * pi / kkizami * i;
  x = nx; y = ny;
  nx = x3 + ((a + b) * Math.Cos(k) - b * Math.Cos((a + b) / b * k));
  ny = y3 - ((a + b) * Math.Sin(k) - b * Math.Sin((a + b) / b * k));
  g.DrawLine(pen, (int)x, (int)y, (int)nx, (int)ny);
}

内サイクロイド

Graphics g = pictureBox1.CreateGraphics();
Pen pen = new Pen(Color.Black);
double pi = 3.14159;
int x3 = pictureBox1.Width / 2;
int y3 = pictureBox1.Height / 2;
double r1;
int kkizami = 100;
int shukai = 50;
double a = 100, b = 23;
double k, x = 0, y = 0, nx = 0, ny = 0;
for (int i = 0; i < kkizami * shukai; i++)
{
  k = 2 * pi / kkizami * i;
  if (i == 0)
  {
     x = x3 + ((a - b) * Math.Cos(k) + b * Math.Cos((a - b) / b * k));
     y = y3 - ((a - b) * Math.Sin(k) - b * Math.Sin((a - b) / b * k));
  }
  else
  {
     x = nx;
     y = ny;
  }
     nx = x3 + ((a - b) * Math.Cos(k) + b * Math.Cos((a - b) * k / b));
     ny = y3 - ((a - b) * Math.Sin(k) - b * Math.Sin((a - b) * k / b));
     g.DrawLine(pen, (int)x, (int)y, (int)nx, (int)ny);
  }
}

セルオートマトン例

ランダムウォーク

新しいクラスの定義

ランダムウォークする固体をクラスとして定義する。

  • プロジェクト」メニューから「クラスの追加」でクラス名を入力する。
  • クラス名は、自由につけてよい。
  • クラスの定義の中にメンバー変数とメソッドを記述する。
  • 変数やクラス名の名前の付け方のヒント(文法ではない。様々な流儀がある)
    • クラス名 Pascal型 KougeiTaro
    • 変数名 Camel型 kougeiTaro
    class RandWalker
    {
        public int dx { get; set; } // X軸の歩幅
        public int dy { get; set; } // Y軸の歩幅
        public int X { get; set; } // ウォーカーの現在位置のX座標
        public int Y { get; set; } // ウォーカーの現在位置のX座標
        public int r { get; set; } // ウォーカーの大きさ(直径)
        public int MaxHeight { get; set; } // ウォーカーの移動範囲のX座標の最大値(右の壁)
        public int MaxWidth { get; set; } // ウォーカーの移動範囲のY座標の最大値(下の壁)
        private Random rnd = new Random(); //乱数の定義

        public void walk() {
          int d = rnd.Next(1, 5); //1から4までの乱数を発生
            switch(d)
            {
                case 1:  // 1のときX軸の右(正)へ進む
                    X = X + dx;
                    break;
                case 2:  // 2のときX軸の左(負)へ進む
                    X = X - dx;
                    break;
                case 3: // 3のときY軸の下(正)へ進む
                    Y = Y + dy;
                    break;
                case 4: // 4のときY軸の上(負)へ進む
                    Y = Y - dy;
                    break;
            }
            if (X <= 0) // 壁にぶつかると進めない
                X = 1;
            if (X >= MaxWidth)
                X = MaxWidth;
            if (Y <= 0)
                Y = 1;
            if (Y >= MaxHeight)
                Y = MaxHeight;
        }
    }

メインプログラムでウォーカーをランダムに歩かせる。

  • pictureBox1に描画
  • timer1で、歩かせる。
  • buttonでタイマーのstart, pause, clearを指定
  • クラスRandwalkerのメンバーやメソッドは、以下のように呼び出す。
    • walker.X
    • walker.walk()
    public partial class Form1 : Form
    {
        //グラフィック、ペン、ブラシ、ウォーカーをグローバルとして宣言
        Graphics g;
        Pen pen;
        SolidBrush brush;
        private RandWalker walker;

        public Form1()
        {
            InitializeComponent();
            g = pictureBox1.CreateGraphics();

            pen = new Pen(Color.Black);
            brush = new SolidBrush(Color.Black);
            walker = new RandWalker() // ウォーカーの初期値を指定
            {
                dx = 5,
                dy =5,
                r = 5,
                X = (int)pictureBox1.Width / 2,
                Y = (int)pictureBox1.Height / 2,
                MaxWidth = (int)pictureBox1.Width,
                MaxHeight = (int)pictureBox1.Height,
            };
        }

        private void button1_Click(object sender, EventArgs e)
        {
            timer1.Start();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            timer1.Stop();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            g.Clear(Color.White);
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            //ウォーカーの足跡をライトグレイで上書きする
            pen.Color = Color.LightGray;
            brush.Color = Color.LightGray;
            g.DrawRectangle(pen, walker.X, walker.Y, walker.r, walker.r);
            g.FillRectangle(brush, walker.X, walker.Y, walker.r, walker.r);
 
            //ウォーカーを歩かせ、現在位置を赤で描く
            walker.walk();
            pen.Color = Color.Red;
            g.DrawRectangle(pen, walker.X, walker.Y, walker.r, walker.r);
            brush.Color = Color.Red;
            g.FillRectangle(brush, walker.X, walker.Y, walker.r, walker.r);
        }
    }

物理法則

等速移動

クラスのwalkメソッド

  • 位置の変化(速度)であるdx dyが常に一定値
        public void walk()
        {
            // 等速移動
            X = X + dx;
            Y = Y + dy;

            //壁で跳ね返る
            if (X < 0)
            {
                X = -X;
                dx = dx * (-1);
            }
            if (X > MaxWidth)
            {
                X = MaxWidth - (X - MaxWidth);
                dx = dx * (-1);
            }
            if (Y < 0)
            {
                Y = -Y;
                dy = dy * (-1);
            }
            if (Y > MaxHeight)
            {
                Y = MaxHeight - (Y - MaxHeight);
                dy = dy * (-1);
            }
        }
等加速度移動

クラスのwalkメソッド

  • x軸の位置の変化であるdxは、常に一定値
  • y軸の位置の変化であるdyは、一定の割合で変化
            // 等加速度移動
            dy++;
            X = X + dx;
            Y = Y + dy;
万有引力
恒星を固定する

クラスのwalkメソッド

  • 惑星位置の変化であるdx,dyは、恒星との距離の2乗に反比例し、恒星の質量に比例する。
    class planet
    {

        public double dx { get; set; }
        public double dy { get; set; }
        public int X { get; set; }
        public int Y { get; set; }
        public int r { get; set; }

        public int X0 { get; set; } //恒星の座標
        public int Y0 { get; set; }
        public double m { get; set; } //自分の質量

        public int MaxHeight { get; set; }
        public int MaxWidth { get; set; }

        public void walk()
        {
            double dd = (X - X0) * (X - X0) + (Y - Y0) * (Y - Y0); //恒星との距離の2乗
            dx = dx - ( X - X0 ) * m /dd;
            dy = dy - ( Y - Y0 ) * m / dd;
            X = (int)(X + dx);
            Y = (int)(Y + dy);

            //壁で跳ね返る
            if (X < 0)
            {
                X = -X;
            }
            if (X > MaxWidth)
            {
                X = MaxWidth - (X - MaxWidth);
            }
            if (Y < 0)
            {
                Y = -Y;
            }
            if (Y > MaxHeight)
            {
                Y = MaxHeight - (Y - MaxHeight);
            }
        }
    }

        // Planet classのインスタンスmarsをグローバルに宣言
        private Planet mars;

        public Form1()
        {
            InitializeComponent();

            // Planet classのインスタンスmarsをグローバルの定義
            mars = new Planet()
            {
                dx = -0.1,
                dy = 4.0,
                r = 5,
                m = 350,
                X = (int)pictureBox1.Width / 7 * 6,
                Y = (int)pictureBox1.Height / 4,
                X0 = (int)pictureBox1.Width / 2,
                Y0 = (int)pictureBox1.Height / 2,
                MaxWidth = (int)pictureBox1.Width,
                MaxHeight = (int)pictureBox1.Height,
            };
        }


2体問題
  • クラスの定義は同様
  • 恒星の座標に相手の座標を代入する。すなわち惑星2つの相互作用とみなす。
    • より正確な位置計算が必要なため、2体の座標データ(X,Y)と(X0,Y0)は、整数(int)ではなく、倍制度(double)で定義する。
    • 重力定数gを導入
    class Planet
    {
        public double dx { get; set; }
        public double dy { get; set; }
        public double X { get; set; }
        public double Y { get; set; }
        public int r { get; set; }
        public double m { get; set; } //質量

        public double X0 { get; set; } //相手の座標
        public double Y0 { get; set; }
        public double m0 { get; set; } //相手の質量

        public int MaxHeight { get; set; }
        public int MaxWidth { get; set; }

        public void walk()
        {
            double g = 0.115;  //重力定数
            double dd = (X - X0) * (X - X0) + (Y - Y0) * (Y - Y0); //相手との距離の2乗
            dx = dx - (X - X0) * m0 / dd * g;
            dy = dy - (Y - Y0) * m0 / dd * g;
            X = X + dx;
            Y = Y + dy;

            //壁で跳ね返る
            
            if (X < 0)
            {
                X = -X;
                dx = -dx * 0.01;
            }
            if (X > MaxWidth)
            {
                X = MaxWidth - (X - MaxWidth);
                dx = -dx;
            }
            if (Y < 0)
            {
                Y = -Y;
                dy = -dy * 0.01;
            }
            if (Y > MaxHeight)
            {
                Y = MaxHeight - (Y - MaxHeight);
                dy = -dy;
            }
        }
    }

2対の座標データ(X,Y)と(X0,Y0)を描画する際に、doubleをintに型変換するために、グローバル変数x1,y1,x2.y2を使用する。

    public partial class Form1 : Form
    {
        //グラフィック、ペン、ブラシ、ウォーカーをグローバルとして宣言
        Graphics g;
        Pen pen;
        SolidBrush brush;
        private Planet mars;
        private Planet virnus;
        int x1, y1, x2, y2;

        public Form1()
        {
            InitializeComponent();

            g = pictureBox1.CreateGraphics();
            pen = new Pen(Color.Black);
            brush = new SolidBrush(Color.Black);

            mars = new Planet() // ウォーカーの初期値を指定
            {
                dx = -0.1,
                dy = 4.0,
                r = 5,
                m = 350,
                X = (int)pictureBox1.Width / 7 * 6,
                Y = (int)pictureBox1.Height / 4,
                MaxWidth = (int)pictureBox1.Width,
                MaxHeight = (int)pictureBox1.Height,
            };

            virnus = new Planet() // ウォーカーの初期値を指定
            {
                dx = 0.1,
                dy = -4.0,
                r = 5,
                m = 300,
                X = (int)pictureBox1.Width / 7 * 5,
                Y = (int)pictureBox1.Height / 4,
                MaxWidth = (int)pictureBox1.Width,
                MaxHeight = (int)pictureBox1.Height,
            };
        }

        private void button1_Click(object sender, EventArgs e)
        {
            timer1.Start();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            timer1.Stop();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            g.Clear(Color.White);
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            //お互いの座標と質量を代入する
            mars.X0 = virnus.X;
            mars.Y0 = virnus.Y;
            mars.m0 = virnus.m;
            virnus.X0 = mars.X;
            virnus.Y0 = mars.Y;
            virnus.m0 = mars.m;

            //足跡をライトグレイで上書きする
            x1 = (int)Math.Round(mars.X);
            y1 = (int)Math.Round(mars.Y);
            x2 = (int)Math.Round(virnus.X);
            y2 = (int)Math.Round(virnus.Y);

            pen.Color = Color.LightGray;
            brush.Color = Color.LightGray;

            g.DrawRectangle(pen, x1, y1, mars.r, mars.r);
            g.FillRectangle(brush, x1, y1, mars.r, mars.r);

            g.DrawRectangle(pen, x2, y2, virnus.r, virnus.r);
            g.FillRectangle(brush, x2, y2, virnus.r, virnus.r);

            //歩かせる
            mars.walk();
            virnus.walk();

            //現在位置を赤と緑で描く
            x1 = (int)Math.Round(mars.X);
            y1 = (int)Math.Round(mars.Y);
            x2 = (int)Math.Round(virnus.X);
            y2 = (int)Math.Round(virnus.Y);

            pen.Color = Color.Red;
            brush.Color = Color.Red;
            g.DrawRectangle(pen, x1, y1, mars.r, mars.r);
            g.FillRectangle(brush, x1, y1, mars.r, mars.r);

            pen.Color = Color.Green;
            brush.Color = Color.Green;
            g.DrawRectangle(pen, x2, y2, virnus.r, virnus.r);
            g.FillRectangle(brush, x2, y2, virnus.r, virnus.r);

        }
    }

色をグラデーションで変化させる例

        //グローバルに色のARGBの値の変数を宣言
        int aa, rr, gg, bb, da, dr, dg, db, x1, y1, x2, y2;

        public Form1()
        {
           //Form1の中で変数の初期値を定義
            aa = 255;  rr = 11; gg = 31; bb = 29;
            da = 1; dr = 1; db = 1; dg = 1;
        }

      private void timer1_Tick(object sender, EventArgs e)
        {
            Random rnd = new Random();
            //Timerの中で変数を徐々に変化させる。
            aa = aa + da;
            rr = rr + dr;
            gg = gg + dg;
            bb = bb + db;
            //変化量をランダムに変更する。
            if (aa > 255){ aa = 255; da = rnd.Next(-3,0); }
            if (aa < 1) { aa = 0; da = rnd.Next(1, 4); }
            if (rr > 255) { rr = 255; dr = rnd.Next(-3, 0); }
            if (rr < 1) { rr = 0; dr = rnd.Next(1, 4); }
            if (gg > 255) { gg = 255; dg = rnd.Next(-3, 0); }
            if (gg < 1) { gg = 0; dg = rnd.Next(1, 4); }
            if (bb > 255) { bb = 255; db = rnd.Next(-3, 0); }
            if (bb < 1) { bb = 0; db = rnd.Next(1, 4); }

            pen.Color = Color.FromArgb(aa, rr, gg, bb);
            brush.Color = Color.FromArgb(aa, rr, gg, bb);
            g.DrawRectangle(pen, x1, y1, mars.r, mars.r);
            g.FillRectangle(brush, x1, y1, mars.r, mars.r);
        }
3体問題の例

クラスの定義

   class Planet
    {
        public double dx { get; set; }
        public double dy { get; set; }
        public double X { get; set; }
        public double Y { get; set; }
        public int r { get; set; }
        public double m { get; set; } //質量

        public double X0 { get; set; } //相手の座標
        public double Y0 { get; set; }
        public double m0 { get; set; } //相手の質量

        public double X1 { get; set; } //相手の座標
        public double Y1 { get; set; }
        public double m1 { get; set; } //相手の質量

        public int MaxHeight { get; set; }
        public int MaxWidth { get; set; }

        public void walk()
        {
            double g = 0.115;
            double dd = (X - X0) * (X - X0) + (Y - Y0) * (Y - Y0); //相手との距離の2乗
            dx = dx - (X - X0) * m0 / dd * g;
            dy = dy - (Y - Y0) * m0 / dd * g;
            X = X + dx;
            Y = Y + dy;

            dd = (X - X1) * (X - X1) + (Y - Y1) * (Y - Y1); //相手との距離の2乗
            dx = dx - (X - X1) * m1 / dd * g;
            dy = dy - (Y - Y1) * m1 / dd * g;
            X = X + dx;
            Y = Y + dy;

            //壁で止まる
            if (X < 0)
            {
                X = -X;
            }
            if (X > MaxWidth)
            {
                X = MaxWidth - (X - MaxWidth);
            }
            if (Y < 0)
            {
                Y = -Y;
            }
            if (Y > MaxHeight)
            {
                Y = MaxHeight - (Y - MaxHeight);
            }
        }
    }

メイン部

    public partial class Form1 : Form
    {
        //グラフィック、ペン、ブラシ、ウォーカーをグローバルとして宣言
        Graphics g;
        Pen pen;
        SolidBrush brush;
        private Planet mars;
        private Planet virnus;
        private Planet jupiter;
        int aa, rr, gg, bb, da, dr, dg, db;
        int x1, y1, x2, y2, x3, y3;

        public Form1()
        {
            InitializeComponent();

            g = pictureBox1.CreateGraphics();
            aa = 255;  rr = 11; gg = 31; bb = 29;
            da = 1; dr = 1; db = 1; dg = 1;
            pen = new Pen(Color.Black);
            brush = new SolidBrush(Color.Black);
            mars = new Planet() // ウォーカーの初期値を指定
            {
                dx = -0.01,
                dy = 0.4,
                r = 5,
                m = 100,
                X = (int)pictureBox1.Width / 7 * 6,
                Y = (int)pictureBox1.Height / 4,
                MaxWidth = (int)pictureBox1.Width,
                MaxHeight = (int)pictureBox1.Height,
            };

            virnus = new Planet() // ウォーカーの初期値を指定
            {
                dx = 0.01,
                dy = -0.4,
                r = 10,
                m = 300,
                X = (int)pictureBox1.Width / 7 * 5,
                Y = (int)pictureBox1.Height / 4,
                MaxWidth = (int)pictureBox1.Width,
                MaxHeight = (int)pictureBox1.Height,
            };

            jupiter = new Planet() // ウォーカーの初期値を指定
            {
                dx = 0.4,
                dy = 0.01,
                r = 7,
                m = 200,
                X = (int)pictureBox1.Width / 7 * 5.5,
                Y = (int)pictureBox1.Height / 4 * 2,
                MaxWidth = (int)pictureBox1.Width,
                MaxHeight = (int)pictureBox1.Height,
            };
        }

        private void button1_Click(object sender, EventArgs e)
        {
            timer1.Start();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            timer1.Stop();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            g.Clear(Color.White);
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            Random rnd = new Random();

            aa = aa + da;
            rr = rr + dr;
            gg = gg + dg;
            bb = bb + db;
            if (aa > 255){ aa = 255; da = rnd.Next(-3,0); }
            if (aa < 1) { aa = 0; da = rnd.Next(1, 4); }
            if (rr > 255) { rr = 255; dr = rnd.Next(-3, 0); }
            if (rr < 1) { rr = 0; dr = rnd.Next(1, 4); }
            if (gg > 255) { gg = 255; dg = rnd.Next(-3, 0); }
            if (gg < 1) { gg = 0; dg = rnd.Next(1, 4); }
            if (bb > 255) { bb = 255; db = rnd.Next(-3, 0); }
            if (bb < 1) { bb = 0; db = rnd.Next(1, 4); }

            mars.X0 = virnus.X;
            mars.Y0 = virnus.Y;
            mars.m0 = virnus.m;
            mars.X1 = jupiter.X;
            mars.Y1 = jupiter.Y;
            mars.m1 = jupiter.m;

            virnus.X0 = jupiter.X;
            virnus.Y0 = jupiter.Y;
            virnus.m0 = jupiter.m;
            virnus.X1 = mars.X;
            virnus.Y1 = mars.Y;
            virnus.m1 = mars.m;

            jupiter.X0 = mars.X;
            jupiter.Y0 = mars.Y;
            jupiter.m0 = mars.m;
            jupiter.X1 = virnus.X;
            jupiter.Y1 = virnus.Y;
            jupiter.m1 = virnus.m;

            //足跡は描かない
            
            //歩かせる
            mars.walk();
            virnus.walk();
            jupiter.walk();

            //現在位置を描く
            x1 = (int)Math.Round(mars.X);
            y1 = (int)Math.Round(mars.Y);
            x2 = (int)Math.Round(virnus.X);
            y2 = (int)Math.Round(virnus.Y);
            x3 = (int)Math.Round(jupiter.X);
            y3 = (int)Math.Round(jupiter.Y);

            pen.Color = Color.Red;
            brush.Color = Color.Red;
            pen.Color = Color.FromArgb(aa, rr, gg, bb);
            brush.Color = Color.FromArgb(aa, rr, gg, bb);
            g.DrawEllipse(pen, x1, y1, mars.r, mars.r);
            g.FillEllipse(brush, x1, y1, mars.r, mars.r);

            pen.Color = Color.Green;
            brush.Color = Color.Green;
            pen.Color = Color.FromArgb(bb, aa, rr, gg);
            brush.Color = Color.FromArgb(bb, aa, rr, gg);
            g.DrawEllipse(pen, x2, y2, virnus.r, virnus.r);
            g.FillEllipse(brush, x2, y2, virnus.r, virnus.r);

            pen.Color = Color.FromArgb(gg, bb, aa, rr);
            brush.Color = Color.FromArgb(gg, bb, aa, rr);
            g.DrawEllipse(pen, x3, y3, jupiter.r, jupiter.r);
            g.FillEllipse(brush, x3, y3, jupiter.r, jupiter.r);

        }
    }

ラングトンのアリ

新しいクラスの定義

ラングトンのアリのローカルルールに従って動く固体をクラスとして定義する。

  • Antクラスは、色の情報を持っているので、Ant.csの冒頭に以下のライブラリーを追加する。
using System.Drawing;

Antクラスの例

    class Ant
    {
        public int d { get; set; }
        public int X { get; set; }
        public int Y { get; set; }
        public int r { get; set; }
        public int MaxHeight { get; set; }
        public int MaxWidth { get; set; }
        private int direction;
        public Color myColor;

        public Color walk( Color nowColor )
        {
            Color retColor;

            if (nowColor == Color.White)
            {
                retColor = myColor;
                direction = (direction + 3) % 4;
            }
            else {
                retColor = Color.White;
                direction = (direction + 1) % 4;
            }
            switch( direction )
            {
                case 0: // north
                    Y = Y - d;
                    break;
                case 1: //east
                    X = X + d;
                    break;
                case 2: // south
                    Y = Y + d;
                    break;
                case 3: // west
                    X = X - d;
                    break;
            }
            // トーラス(ドーナツ型)の世界
            if (X < 0) // 左に抜けると右から出てくる。
                X = MaxWidth + X;
            if (X >= MaxWidth) // 右に抜けると左から出てくる。
                X = X - MaxWidth;
            if (Y < 0) // 上に抜けると下から出てくる。
                Y = MaxHeight + Y;
            if (Y >= MaxHeight)// 下に抜けると上から出てくる。
                Y = Y - MaxHeight;

            return retColor;
        }

    }

メインプログラムでアリをローカルルールに従って歩かせる。

    public partial class Form1 : Form
    {
        Graphics g;
        Pen pen;
        SolidBrush brush;
        private Ant _ant;
        Color antColor1;
        Color antColor2;
        private Color[] map1;
        int X1, Y1;

        public Form1()
        {
            InitializeComponent();
            // 上の行は最初から書かれているので、コピペしない
       
            g = pictureBox1.CreateGraphics();

            map1 = new Color[pictureBox1.Width * pictureBox1.Height];
            for (int i = 0; i < map1.Length; i++)
            {
                map1[i] = Color.White;
            }

            pen = new Pen(Color.Black);
            brush = new SolidBrush(Color.Black);
            _ant = new Ant()
            {
                d = 2,
                X = (int)pictureBox1.Width / 3,
                Y = (int)pictureBox1.Height / 3,
                r = 2,
                MaxWidth = (int)pictureBox1.Width,
                MaxHeight = (int)pictureBox1.Height,
                myColor = Color.SkyBlue,
            };

        }

        private void button1_Click(object sender, EventArgs e)
        {
            timer1.Start();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            pen.Color = antColor2;
            g.DrawRectangle(pen, X1, Y1, _ant.r, _ant.r);
            brush.Color = antColor2;
            g.FillRectangle(brush, X1, Y1, _ant.r, _ant.r);

            X1 = _ant.X;
            Y1 = _ant.Y;
            antColor1 = map1[ X1 + Y1 * pictureBox1.Width];
            antColor2 = _ant.walk(antColor1);
            map1[X1 + Y1 * pictureBox1.Width] = antColor2;

            pen.Color = Color.Red;
            g.DrawRectangle(pen, X1, Y1, _ant.r, _ant.r);
            brush.Color = Color.Red;
            g.FillRectangle(brush, X1, Y1, _ant.r, _ant.r);

        }
    }

1次元セルオートマトン

実行例

// グラフィック,描画ブラシ,乱数の準備
Graphics g = pictureBox1.CreateGraphics();
SolidBrush brush = new SolidBrush(Color.Black);
Random rnd = new Random();

// セルの状態格納用の2次元整数型配列を用意
int ookisa = 100;// 配列の大きさ
int[ , ] cell = new int[ookisa, ookisa];

//セルの初期状態
for (int j = 0; j < ookisa; j++)
{
  cell[0, j] = rnd.Next(0, 0);
}
cell[0, ookisa / 2] = 128;

//セルの状態遷移則
for (int i = 1; i < ookisa; i++)
{
  for (int j = 1; j < ookisa - 1; j++)
  {
     cell[i, j] = (cell[i - 1, j - 1] + cell[i - 1, j + 1]) % 256;
  }
}

//セルの描画
int pixsz = 5;
for (int i=0; i < ookisa; i++){
  for (int j=0; j < ookisa; j++)
  {
    brush.Color = Color.FromArgb(255, cell[i, j], 0, 0);
    g.FillRectangle(brush, j * pixsz, i * pixsz, pixsz, pixsz);
  }
}

変化形

//セルの初期状態
for (int j = 0; j < ookisa; j++)
{
   cell[0, j] = rnd.Next(0, 0) ;
}
cell[0, ookisa / 2] = 7;
cell[0, ookisa / 3] = 6;
cell[0, ookisa / 4] = 3;
cell[0, ookisa / 3 * 2] = 70;

//セルの状態遷移則
for (int i = 1; i < ookisa; i++)
{
  for (int j = 1; j < ookisa - 1; j++)
  {
     cell[i, j] = (cell[i - 1, j - 1] + cell[i - 1, j + 1] + cell[i - 1, j] ) % 256;
  }
}

//セルの描画
int pixsz = 5;
for (int i=0; i < ookisa; i++)
{
  for (int j=0; j < ookisa; j++)
  {
     brush.Color = Color.FromArgb(255, cell[i, j], cell[j, i], 0);
     g.FillRectangle(brush, j * pixsz, i * pixsz, pixsz, pixsz);
  }
}
個人用ツール
名前空間

変種
操作
案内
ツールボックス