コンピュータが乱数でプレイ

コンピュータが乱数でプレイします。

前田稔の超初心者のプログラム入門

プログラムの作成

  1. メモ帳などでタイプして osero.java の名前で保存して下さい。
    //★ コンピュータが乱数でプレイ(普通に起動出来ます)    前田 稔
    import java.applet.*;
    import java.awt.*;
    import javax.swing.*;
    import java.util.*;
    import java.awt.event.*;
    import com.sun.j3d.utils.applet.MainFrame;
    
    public class osero extends JApplet implements MouseListener
    {   oseroobj    obj;
        byte        ply= 1;     // 1:black  -1:white
        // 0:初期  1:ManPlay  2:CompPlay  3:GameOver
        int         state= 0;
    
        // main Method
        public static void main(String[] args)
        {   new MainFrame(new osero(), 640, 480);  }
    
        // Initialize
        public void init()
        {   obj = new oseroobj();
            addMouseListener(this);
            setBackground(new Color(200,200,200));
        }
    
        // Paint
        public void paint(Graphics g)
        {
            Dimension  size = getSize();
            g.setColor(getBackground());
            g.fillRect(0, 0, size.width, size.height);
            obj.View(g);
        }
    
        // Mouse Click
        public void mouseClicked(MouseEvent e)
        {   int     rc;
            switch(state)
            {   case 0:
                    System.out.println("ゲームを開始します");
                    state= 1;
                    break;
                case 1:     //※ManPlay
                    rc= obj.Check_Play(ply,e.getX(),e.getY());
                    switch(rc)
                    {   case 0:
                            ply= (byte)(0-ply);
                            state= 2;       //2:CompPlay
                            break;
                        case 1:
                            System.out.println("あなたはパスです");
                            ply= (byte)(0-ply);
                            break;
                        case 2:
                            System.out.println("エラーです");
                            break;
                        case 3:
                            System.out.println("ゲーム終了です");
                            System.out.println("黒石=" + obj.B_C + "  白石=" + obj.W_C);
                            state= 3;       //3:GameOver
                            break;
                    }
                    break;
                case 2:     //※CompPlay
                    rc= obj.Comp_Play(ply);
                    switch(rc)
                    {   case 0:
                            ply= (byte)(0-ply);
                            state= 1;       //1:ManPlay
                            break;
                        case 1:
                            System.out.println("私はパスです");
                            ply= (byte)(0-ply);
                            state= 1;       //1:ManPlay
                            break;
                        case 2:
                            System.out.println("プログラムのエラーです");
                            break;
                        case 3:
                            System.out.println("ゲーム終了です");
                            System.out.println("黒石=" + obj.B_C + "  白石=" + obj.W_C);
                            state= 3;       //3:GameOver
                            break;
                    }
                    break;
            }
            repaint();
        }
    
        public void mousePressed(MouseEvent e){}
        public void mouseReleased(MouseEvent e){}
        public void mouseEntered(MouseEvent e){}
        public void mouseExited(MouseEvent e){}
    }
    
    //★ オセロ Object Class
    class oseroobj extends JApplet
    {   byte    T[][] = new byte[8][8];
        int     WSIZE= 50;              //格子のサイズ
        int     KSIZE= (WSIZE*8/10);    //駒の直径
        Point   S[] = new Point[30];    //手の検索
        Random  Rand;                   //乱数の発生
        int     Xpos,Ypos;              //プレイの位置
        int     B_C,W_C;                //駒の数
        int     x,y,i,j;
    
        // Constructor
        oseroobj()
        {
            T[4][3]=T[3][4]= 1;         //黒
            T[3][3]=T[4][4]= -1;        //白
            Rand = new Random();        //乱数の初期化
            for(i=0; i<30; i++) S[i]= new Point();
        }
    
        // 盤を描画
        void  View(Graphics g)
        {
            g.setColor(new Color(0,140,0));
            g.fillRect(10,10,WSIZE*8+20,WSIZE*8+20);
            g.setColor(Color.black);
            for(i=0; i<9; i++)
            {   g.drawLine(20,WSIZE*i+20,WSIZE*8+20,WSIZE*i+20);    // 横線
                g.drawLine(WSIZE*i+20,20,WSIZE*i+20,WSIZE*8+20);    // 縦線
            }
            for(i=0,y=WSIZE-25; i<8; i++,y+=WSIZE)
            {   for(j=0,x=WSIZE-25; j<8; j++,x+=WSIZE)
                {   if (T[i][j]!=0) Koma(g,x,y,T[i][j]);
                }
            }
        }
    
        // 駒を表示する
        void  Koma(Graphics g, int xp, int yp, byte c)
        {
            if (c==1)
            {   g.setColor(Color.black);
                g.fillArc(xp,yp,KSIZE,KSIZE,0,360);
            }
            if (c==-1)
            {   g.setColor(Color.white);
                g.fillArc(xp,yp,KSIZE,KSIZE,0,360);
            }
        }
    
        // コンピュータがプレイする
        int  Comp_Play(byte c)
        {   int     n,hand;
            n= Search(c,T,S);
            if (n==0)
            {   if (Search((byte)-c,T,S)>0) return 1;   //パス
                //終局(コマをカウント)
                B_C= Count((byte)1,T);
                W_C= Count((byte)-1,T);
                return 3;
            }
            hand= Rand.nextInt(n);
            Xpos= S[hand].x;
            Ypos= S[hand].y;
            if (Reverse(c,Xpos,Ypos,T)==false)  return 2;   //プログラムのエラー
            return 0;
        }
    
        // 全ての打てる場所を調べる
        int  Search(byte c, byte t[][], Point s[])
        {   int     n;
            for(n=y=0; y<8; y++)
                for(x=0; x<8 && n<30; x++)
                    if (Check(c,x,y,t))
                    {   s[n].x= x;
                        s[n].y= y;
                        n++;
                    }
            return n;
        }
    
        // 人間のプレイ & 判定
        int  Check_Play(byte c, int xp, int yp)
        {
            SetPos(xp,yp);
            if (Check(c,Xpos,Ypos,T))
            {   Reverse(c,Xpos,Ypos,T);             //駒を置く
                return 0;                           //Play
            }
            if (Search(c,T,S)>0)    return 2;       //エラー
            if (Search((byte)-c,T,S)>0) return 1;   //手番側がパス
            //ゲーム終了
            B_C= Count((byte)1,T);
            W_C= Count((byte)-1,T);
            return 3;
        }
    
        // 置けるかどうかをチェックする
        boolean  Check(byte c, int xp, int yp, byte t[][])
        {   int     k,l;
            if (yp>7 || xp>7 || yp<0 || xp<0 || c==0 || t[yp][xp]!=0)   return false;
            for(k=-1; k<2; k++)
                for(l=-1; l<2; l++)
                {   i=yp+k;
                    j=xp+l;
                    if (i<8 && j<8 && i>=0 && j>=0 && t[i][j]==-c)
                    {   for(; i<8 && j<8 && i>=0 && j>=0 && t[i][j]==-c; i+=k,j+=l);
                        if (i<8 && j<8 && i>=0 && j>=0 && t[i][j]==c)   return true;
                    }
                }
            return false;   //置くことができない
        }
    
        // t[yp][xp] に駒を置いて、挟んだ駒を裏返す
        boolean  Reverse(byte c, int xp, int yp, byte t[][])
        {   int     k,l;
            boolean sw;
            if (yp>7 || xp>7 || yp<0 || xp<0 || c==0 || t[yp][xp]!=0)   return false;
            sw= false;
            for(k=-1; k<2; k++)
                for(l=-1; l<2; l++)
                {   i=yp+k;
                    j=xp+l;
                    if (i<8 && j<8 && i>=0 && j>=0 && t[i][j]==-c)
                    {   for(; i<8 && j<8 && i>=0 && j>=0 && t[i][j]==-c; i+=k,j+=l);
                        if (i>7 || j>7 || i<0 || j<0 || t[i][j]!=c) continue;
                        for(i-=k,j-=l; i!=yp || j!=xp; i-=k,j-=l)   t[i][j]= c;
                        sw= true;
                    }
                }
            if (sw==false)  return false;
            t[yp][xp]= c;
            return true;
        }
    
        // クリックした座標を盤の位置に変換して Xpos Ypos に格納する
        void  SetPos(int xp, int yp)
        {   Xpos= (xp-20)/WSIZE;
            Ypos= (yp-20)/WSIZE;
        }
    
        // 駒をカウントする
        int  Count(byte c, byte t[][])
        {   int n;
            for(n=y=0; y<8; y++)
                for(x=0; x<8; x++)
                    if (t[y][x]==c)     n++;
            return n;
        }
    }
    
  2. Java Applet のプログラムですが、普通に起動することも出来ます。
    開発段階では Applet で起動するよりも何かと便利です。
    Microsoft Windows [Version 6.1.7600]
    Copyright (c) 2009 Microsoft Corporation.  All rights reserved.
    
    C:\Users\maeda>cd c:\tmp
    
    c:\TMP>javac osero.java
    
    c:\TMP>java osero
    
    また Jcpad を使用するとソースプログラムの作成から実行までを簡単に操作することができます。

プログラムの説明

  1. 乱数を使うので util.* を import して下さい。
    マウスを使うので awt.event.* を import して MouseListener を implements して下さい。
    Applet のプログラムを普通に起動するときは applet.MainFrame を import して main Method を記述して下さい。
    import java.util.*;
    import java.awt.event.*;
    import com.sun.j3d.utils.applet.MainFrame;
    
    public class osero extends JApplet implements MouseListener
    {   oseroobj    obj;
        ・・・
        // main Method
        public static void main(String[] args)
        {   new MainFrame(new osero(), 640, 480);  }
    
  2. state でゲームの進行を制御します。
    1. state 0: ゲームの初期状態です。
    2. state 1: 人間側の手番です。
      マウスのクリックでプレイして下さい。
    3. state 2: コンピュータ側の手番です。
      コンピュータは乱数で打つ手を選択します。
    4. state 3: ゲームの終了です。
    {   oseroobj    obj;
        byte        ply= 1;     // 1:black  -1:white
        // 0:初期  1:ManPlay  2:CompPlay  3:GameOver
        int         state= 0;
    
  3. マウスがクリックされたときの処理です。
    state==0 のときは、ゲームの開始メッセージを表示して、state を 1 に設定します。
    state==1 のときは、クリックされた座標にコマを置きます。
    Check_Play() が人間がプレイするメソッドです。
    state==2 のときは、コンピュータが乱数でプレイします。
    Comp_Play() がコンピュータがプレイするメソッドです。
        // Mouse Click
        public void mouseClicked(MouseEvent e)
        {   int     rc;
            switch(state)
            {   case 0:
                    System.out.println("ゲームを開始します");
                    state= 1;
                    break;
                case 1:     //※ManPlay
                    rc= obj.Check_Play(ply,e.getX(),e.getY());
                    switch(rc)
                    {   case 0:
                            ply= (byte)(0-ply);
                            state= 2;       //2:CompPlay
                            break;
                        case 1:
                            System.out.println("あなたはパスです");
                            ply= (byte)(0-ply);
                            break;
                        case 2:
                            System.out.println("エラーです");
                            break;
                        case 3:
                            System.out.println("ゲーム終了です");
                            System.out.println("黒石=" + obj.B_C + "  白石=" + obj.W_C);
                            state= 3;       //3:GameOver
                            break;
                    }
                    break;
                case 2:     //※CompPlay
                    rc= obj.Comp_Play(ply);
                    switch(rc)
                    {   case 0:
                            ply= (byte)(0-ply);
                            state= 1;       //1:ManPlay
                            break;
                        case 1:
                            System.out.println("私はパスです");
                            ply= (byte)(0-ply);
                            state= 1;       //1:ManPlay
                            break;
                        case 2:
                            System.out.println("プログラムのエラーです");
                            break;
                        case 3:
                            System.out.println("ゲーム終了です");
                            System.out.println("黒石=" + obj.B_C + "  白石=" + obj.W_C);
                            state= 3;       //3:GameOver
                            break;
                    }
                    break;
            }
            repaint();
        }
    
  4. oseroobj Class です。
    乱数を使うので Random Rand を定義して、初期化して下さい。
        Random  Rand;                   //乱数の発生
           ・・・
            Rand = new Random();        //乱数の初期化
    
  5. コンピュータがプレイする Comp_Play() メソッドです。
    Search(c,T,S); で全ての手を調べて、乱数で打つ手を決めます。
    コンピュータ側がパスのときは、人間側の手を調べます。
    両方パスのときは終局です。
    Reverse(c,Xpos,Ypos,T) でコマを置いて、挟んだコマを裏返します。
    プログラムが正しければ Reverse() でエラーになることは無いのですが、念の為に調べています。
    リターン値は「0:正常なプレイ, 1:コンピュータ側はパス, 2:プレイのエラー, 3:終局」です。
        // コンピュータがプレイする
        int  Comp_Play(byte c)
        {   int     n,hand;
            n= Search(c,T,S);
            if (n==0)
            {   if (Search((byte)-c,T,S)>0) return 1;   //パス
                //終局(コマをカウント)
                B_C= Count((byte)1,T);
                W_C= Count((byte)-1,T);
                return 3;
            }
            hand= Rand.nextInt(n);
            Xpos= S[hand].x;
            Ypos= S[hand].y;
            if (Reverse(c,Xpos,Ypos,T)==false)  return 2;   //プログラムのエラー
            return 0;
        }
    
  6. 全ての手を調べる Search() メソッドです。
    Check(c,x,y,t) メソッドでコマを置くことが出来るか否かを判定します。
    コマを置くことが出来る座標を s[] に登録します。
        // 全ての打てる場所を調べる
        int  Search(byte c, byte t[][], Point s[])
        {   int     n;
            for(n=y=0; y<8; y++)
                for(x=0; x<8 && n<30; x++)
                    if (Check(c,x,y,t))
                    {   s[n].x= x;
                        s[n].y= y;
                        n++;
                    }
            return n;
        }
    
  7. クリックされた座標から人間側の手を調べて、プレイする Check_Play() メソッドです。
    SetPos(xp,yp) メソッドでクリックされた座標からコマの位置を Xpos,Ypos に設定します。
    Check(c,Xpos,Ypos,T) でコマを置くことが出来るかを調べて Reverse(c,Xpos,Ypos,T) でプレイします。
    プレイのエラーとパスと終局を調べています。
    リターン値は「0:正常なプレイ, 1:人間側はパス, 2:プレイのエラー, 3:終局」です。
        // 人間のプレイ & 判定
        int  Check_Play(byte c, int xp, int yp)
        {
            SetPos(xp,yp);
            if (Check(c,Xpos,Ypos,T))
            {   Reverse(c,Xpos,Ypos,T);             //駒を置く
                return 0;                           //Play
            }
            if (Search(c,T,S)>0)    return 2;       //エラー
            if (Search((byte)-c,T,S)>0) return 1;   //手番側がパス
            //ゲーム終了
            B_C= Count((byte)1,T);
            W_C= Count((byte)-1,T);
            return 3;
        }
    
  8. 置けるか否かを調べる Check() メソッドです。
    xp,yp の座標にコマを置いて、相手のコマを挟むことが出来るかを調べます。
        // 置けるかどうかをチェックする
        boolean  Check(byte c, int xp, int yp, byte t[][])
        {   int     k,l;
            if (yp>7 || xp>7 || yp<0 || xp<0 || c==0 || t[yp][xp]!=0)   return false;
            for(k=-1; k<2; k++)
                for(l=-1; l<2; l++)
                {   i=yp+k;
                    j=xp+l;
                    if (i<8 && j<8 && i>=0 && j>=0 && t[i][j]==-c)
                    {   for(; i<8 && j<8 && i>=0 && j>=0 && t[i][j]==-c; i+=k,j+=l);
                        if (i<8 && j<8 && i>=0 && j>=0 && t[i][j]==c)   return true;
                    }
                }
            return false;   //置くことができない
        }
    
  9. xp,yp の座標にコマを置いて、挟んだコマを裏返す Reverse() メソッドです。
    念のためにエラーか否かを調べています。
        // t[yp][xp] に駒を置いて、挟んだ駒を裏返す
        boolean  Reverse(byte c, int xp, int yp, byte t[][])
        {   int     k,l;
            boolean sw;
            if (yp>7 || xp>7 || yp<0 || xp<0 || c==0 || t[yp][xp]!=0)   return false;
            sw= false;
            for(k=-1; k<2; k++)
                for(l=-1; l<2; l++)
                {   i=yp+k;
                    j=xp+l;
                    if (i<8 && j<8 && i>=0 && j>=0 && t[i][j]==-c)
                    {   for(; i<8 && j<8 && i>=0 && j>=0 && t[i][j]==-c; i+=k,j+=l);
                        if (i>7 || j>7 || i<0 || j<0 || t[i][j]!=c) continue;
                        for(i-=k,j-=l; i!=yp || j!=xp; i-=k,j-=l)   t[i][j]= c;
                        sw= true;
                    }
                }
            if (sw==false)  return false;
            t[yp][xp]= c;
            return true;
        }
    
  10. あとは、クリックした座標を盤の位置に変換する SetPos() メソッドと、駒をカウントする Count() メソッドです。

[Next Chapter ↓] オセロゲームβ版
[Previous Chapter ↑] オセロゲームの盤と駒を表示

Java Game Program