三目並べゲーム

ディープラーニングの準備が整った所で、いよいよゲーム本体の作成です。
これまでは Console Mode でしたが、ゲーム本体は Windows Mode です。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プログラムの説明

  1. 三目並べゲーム CSForm.cs のソースコードです。
    コンピュータは空いている箇所を探し出して駒を置くだけですが、交互にプレイ出来ます。
    // コンピュータとプレイする
    using System;
    using System.Drawing;
    using System.Windows.Forms;
    public class Pos
    {   public int y=0;     // Y 座標
        public int x=0;     // X 座標
    }
    
    public class MyForm : Form
    {
        int[,] m_t = new int[3, 3];
        int[,] dat = new int[9, 2]; // 手の記録
        int     m_num;              // dat のIDX
        bool    m_sente= true;      // 先手フラグ
        int     x,y;
    
        public MyForm()
        {   Init();
            BackColor = SystemColors.AppWorkspace;
            Width  = 250;
            Height = 270;
            Paint += new PaintEventHandler(MyHandler);
            MouseDown += new MouseEventHandler(OnMyMouseDown);
        }
        // ウインドウの描画
        private void MyHandler(object sender, PaintEventArgs e)
        {   Graphics g = e.Graphics;
            int ret;
            g.DrawImage(new Bitmap("c:\\data\\test\\game3.gif"), new PointF(10F, 10F));
            for (y = 0; y < 3; y++)
                for (x = 0; x < 3; x++)
                {   if (m_t[y, x]==1) g.DrawImage(new Bitmap("c:\\data\\test\\koma_b.gif"), new PointF(x * 61 + 28, y * 61 + 24));
                    if (m_t[y, x]==-1) g.DrawImage(new Bitmap("c:\\data\\test\\koma_w.gif"), new PointF(x * 61 + 28, y * 61 + 24));
                }
            ret= Fine(m_t);
            if (ret==1)     MessageBox.Show("黒の勝ち");
            if (ret==-1)    MessageBox.Show("白の勝ち");
        }
        // マウスのクリックでプレイ
        private void OnMyMouseDown(object sender, MouseEventArgs e)
        {   Pos p = new Pos();
            int c= 0;
            if (e.Button == MouseButtons.Right)
            {   Init();
                m_sente= !m_sente;
                Invalidate();
                return;
            }
            p.x = (e.X-28)/61;
            p.y = (e.Y-24)/61;
            if (m_num%2==0)         // 先手番
            {   if (!m_sente)       // マシンが先手
                {   p= Play(m_t);  }
                c = 1;
            }
            else                    // 後手番
            {   if (m_sente)        // マシンが後手
                {   p= Play(m_t);  }
                c = -1;
            }   
            if (m_t[p.y,p.x]!=0)
            {   MessageBox.Show("Miss Play");
                return;
            }
            m_t[p.y,p.x]= c;
            dat[m_num,0]= p.y;
            dat[m_num,1]= p.x;
            m_num++;
            Invalidate();
        }               
        // 空いている箇所を選択
        public Pos Play(int[,] t)
        {   Pos p = new Pos();
            for(p.y=0; p.y<3; p.y++)
                for(p.x=0; p.x<3; p.x++)
                {   if (t[p.y, p.x] == 0)   return p;
                }
            return p;
        }
        // 終了判定
        public int Fine(int[,] t)
        {   int[] tw = new int[8];
            int     i;
            for(i=0; i<8; i++)  tw[i] = 0;
            for(i=0; i<3; i++)
            {   tw[0] += t[0,i];
                tw[1] += t[1,i];
                tw[2] += t[2,i];
                tw[3] += t[i,0];
                tw[4] += t[i,1];
                tw[5] += t[i,2];
                tw[6] += t[i,i];
                tw[7] += t[i,2-i];
            }
            for(i=0; i<8; i++)
            {   if (tw[i]==3)   return 1;
                if (tw[i]==-3)  return -1;
            }
            return 0;
        }
        // ゲームの初期化
        public void Init()
        {   int  x,y;
            for(y=0; y<3; y++)
                for(x=0; x<3; x++)
                    m_t[y,x] = 0;
            m_num= 0;
        }
    }
    
    class image01
    {
        public static void Main()
        {
            MyForm mf = new MyForm();
            Application.Run(mf);
        }
    }
    
  2. 将棋や囲碁でコンピュータがプロを負かすほど強くなってきました。
    コンピュータが自分で学習するAI(人工知能 artificial insemination)のおかげです。
    将棋や囲碁で使われるディープラーニングと呼ばれる学習機能に少しでも触れられたらとオセロゲームで始めたのですが、そう簡単ではないようです。
    そこでもっと簡単な三目並べゲームを材々にしてプログラミングしてみます。
    ディープラーニングの基本は、これまでの説明 三目並べの学習 などを参照して下さい。
    三目並べゲームのプログラムは Windows Mode で作成します。
    マウスのクリックで駒を置くプログラムは 挟んだ駒を裏返す などを参照して下さい。
  3. 三目並べのゲームプログラム(このプログラム)の操作法です。
    人間とコンピュータが対戦するプログラムです。
    人間(プレイヤー)の先手でゲームが始まります。
    3*3の盤をクリックすると、黒の駒が置かれます。
    次に盤上をクリックすると、コンピュータの手番で白の駒が置かれます。
    交互に駒を置いて3目並ぶか、9手打って引き分けになるとゲームが終了します。
    マウスを右クリックすると手番を変えて最初から始まります。
  4. m_t[3,3] は三目並べゲームの盤です。
    dat[9,2] は1局の手順を記録する領域です。
    m_num は何手目かを示すゲームの記録(dat)の Index です。
    m_sente は先手/後手のフラグで true のときはプレイヤーの先手です。
    public class MyForm : Form
    {   int[,] m_t = new int[3, 3];
        int[,] dat = new int[9, 2]; // 手の記録
        int     m_num;              // dat のIDX
        bool    m_sente= true;      // 先手フラグ
    
  5. MyHandler() で盤と駒を描画します。
    game3.gif, koma_b.gif, koma_w.gif を c:\data\test\ のフォルダーに格納して置いて下さい。
    描画が終わると、Fine(m_t) 関数でゲームの終了を調べます。
        private void MyHandler(object sender, PaintEventArgs e)
        {   Graphics g = e.Graphics;
            int ret;
            g.DrawImage(new Bitmap("c:\\data\\test\\game3.gif"), new PointF(10F, 10F));
            for (y = 0; y < 3; y++)
                for (x = 0; x < 3; x++)
                {   if (m_t[y, x]==1) g.DrawImage(new Bitmap("c:\\data\\test\\koma_b.gif"), new PointF(x * 61 + 28, y * 61 + 24));
                    if (m_t[y, x]==-1) g.DrawImage(new Bitmap("c:\\data\\test\\koma_w.gif"), new PointF(x * 61 + 28, y * 61 + 24));
                }
            ret= Fine(m_t);
            if (ret==1)     MessageBox.Show("黒の勝ち");
            if (ret==-1)    MessageBox.Show("白の勝ち");
        }
    
  6. マウスのクリックでプレイする OnMyMouseDown() 関数です。
    プレイヤーの手番では、クリックした座標に駒を置きます。
    コンピュータの手番では Play(m_t); 関数で打つ手を決めます。
    (今回は、先頭(左上)から打てる箇所を検索するだけです。)
    エラーをチェックして m_t[3,3] に駒を置いて m_num をカウントアップします。
    Invalidate(); で MyHandler() を呼び出して再描画します。
        private void OnMyMouseDown(object sender, MouseEventArgs e)
        {   Pos p = new Pos();
            int c= 0;
            if (e.Button == MouseButtons.Right)
            {   Init();
                m_sente= !m_sente;
                Invalidate();
                return;
            }
            p.x = (e.X-28)/61;
            p.y = (e.Y-24)/61;
            if (m_num%2==0)         // 先手番
            {   if (!m_sente)       // マシンが先手
                {   p= Play(m_t);  }
                c = 1;
            }
            else                    // 後手番
            {   if (m_sente)        // マシンが後手
                {   p= Play(m_t);  }
                c = -1;
            }   
            if (m_t[p.y,p.x]!=0)
            {   MessageBox.Show("Miss Play");
                return;
            }
            m_t[p.y,p.x]= c;
            dat[m_num,0]= p.y;
            dat[m_num,1]= p.x;
            m_num++;
            Invalidate();
        }               
    
  7. 左上から空いている箇所を選択する Play() 関数です。
        public Pos Play(int[,] t)
        {   Pos p = new Pos();
            for(p.y=0; p.y<3; p.y++)
                for(p.x=0; p.x<3; p.x++)
                {   if (t[p.y, p.x] == 0)   return p;
                }
            return p;
        }
    
  8. ゲームの終了を判定する Fine() 関数です。
    縦,横,斜めに3個並ぶと終局です。
        public int Fine(int[,] t)
        {   int[] tw = new int[8];
            int     i;
            for(i=0; i<8; i++)  tw[i] = 0;
            for(i=0; i<3; i++)
            {   tw[0] += t[0,i];
                tw[1] += t[1,i];
                tw[2] += t[2,i];
                tw[3] += t[i,0];
                tw[4] += t[i,1];
                tw[5] += t[i,2];
                tw[6] += t[i,i];
                tw[7] += t[i,2-i];
            }
            for(i=0; i<8; i++)
            {   if (tw[i]==3)   return 1;
                if (tw[i]==-3)  return -1;
            }
            return 0;
        }
    
  9. ゲームを初期化する Init() 関数です。
        public void Init()
        {   int  x,y;
            for(y=0; y<3; y++)
                for(x=0; x<3; x++)
                    m_t[y,x] = 0;
            m_num= 0;
        }
    

[Next Chapter ↓] 三目並べゲーム-2
[Previous Chapter ↑] 三目並べの自動学習

超初心者のプログラム入門(C# Frame Work)