Java之简单人机五子棋(二)

这一篇接Java之简单人机五子棋(一),讲一下AI算法实现的大致思路。主要思路是分别对黑白棋的局势进行打分,然后在找到评分最高的地方落点。
具体结构如下:
- 首先,point函数负责接收某点坐标和棋子颜色,然后返回对该点的评分。评分函数有四个,分别负责四个方向上的评分,即检测连子情况,依据不同的情况给予相应的分数。
- 其次,wholePoints负责在全局上对每一个点针对某种颜色进行评分,存到形参传入的15*15的评分数组中。
- best_posits负责遍历数组,找到评分最大的点位和个数,放入专门设计用来存储评分最大点的信息的类对象中。
- play 函数则负责对整体局势进行判断,综合比较取评分最高的点进行落子。

代码如下:

package renju;

class BestInfo{
    int bestPoint,bestSum;
    public BestInfo() {
        bestPoint = 0;
        bestSum = 0;
        // TODO 自动生成的构造函数存根
    }
    public BestInfo(int i,int j){
        bestPoint = i;
        bestSum = j;
    }
}
public class AI {

    int color;              //记录AI棋子的颜色
    int points_b[][];       //记录黑棋各落点分数
    int points_w[][];       //记录白棋各落点分数
    position best_b[];  //  记录黑棋最大分数对应的落点位置
    position best_w[];      //记录白棋最大分数对应的落点位置
    BestInfo blackInfo,whiteInfo;   //记录黑白棋分别的最大分数值和最大分数对应的落点位置个数   

    public AI() {
        if(MyControlBoard.whiteC == 1) {
            color = 2;
        }
        else {
            color = 1;
        }
        points_b = new int[15][15];     //记录黑棋各落点分数
        points_w = new int[15][15];     //记录白棋各落点分数
        best_b = new position[250];     //  记录黑棋最大分数对应的落点位置
        best_w = new position[250]; //记录白棋最大分数对应的落点位置
        blackInfo = new BestInfo();
        whiteInfo = new BestInfo();
    }
    public void play() {
        if(!MyControlBoard.started) {
        //  System.out.println("didn't start");
            return;
        }
        if(color == 2 && MyChessBoard.isEmpty) {
            MyChessBoard.chess[7][7] = color;
            MyChessBoard.record(7,7);
        //  System.out.println("empty");
            return;
        }
        int iC,jC = 0,count = 0;
        int xC = 0,yC = 0;
        for(iC =0;iC<15;iC++)
            for(jC = 0;jC < 15;jC++) {
                if(MyChessBoard.chess[iC][jC] != 0) {
                    count+=1;
                    if(count==1) {
                        xC=iC;
                        yC=jC;
                    }
                }
            }
        if(count == 1 && color == 1) {
            try {
                MyChessBoard.chess[xC-1][yC - 1] =color;
                MyChessBoard.record(xC-1,yC-1);
        //      System.out.println("return1");
                return;
            }catch(Exception e){
                MyChessBoard.chess[xC+1][yC + 1] =color;
                MyChessBoard.record(xC-1,yC-1);
        //      System.out.println("return2");
                return;
            }
        }
        wholePoints(points_b, 2);
        wholePoints(points_w, 1);
        best_posits(points_w, best_w,whiteInfo);
        best_posits(points_b, best_b,blackInfo);

    //  System.out.println("color AI ="+color);
    //  System.out.println("black"+blackInfo.bestPoint+"\twhite"+whiteInfo.bestPoint);
        if( blackInfo.bestPoint > whiteInfo.bestPoint )     //黑棋最高分高过白棋,在黑棋最高分对应的位置中选出白棋分数最大的位置落子
        {   
            int a[] = new int[20];
    //      System.out.println("blackInfo.bestSum"+blackInfo.bestSum);
            for(int i = 0;i < blackInfo.bestSum;i++)
            {
                a[i] = point(best_b[i],1);
            }
            int max_w = MAX(a, blackInfo.bestSum);
            for(int i = 0;i < blackInfo.bestSum;i++)
            {
                if(a[i] == max_w)
                {
                    MyChessBoard.chess[best_b[i].x][best_b[i].y] = color;
                    MyChessBoard.record(best_b[i].x,best_b[i].y);
            //      System.out.println("return3");
                    return;
                }
            }
        }
        if( blackInfo.bestPoint < whiteInfo.bestPoint )     //白棋最高分高过黑棋,在白棋最高分对应的位置中选出黑棋分数最大的位置落子
            {
            int a[] = new int[20];
            for(int i = 0;i < whiteInfo.bestSum;i++)
            {
                a[i] = point(best_w[i], 2);
            }
            int max_b = MAX(a, blackInfo.bestSum);
            for(int i = 0;i < whiteInfo.bestSum;i++)
            {
                if(a[i] == max_b)
                {
                    MyChessBoard.chess[best_w[i].x][best_w[i].y] = color;
                    MyChessBoard.record(best_w[i].x,best_w[i].y);
            //      System.out.println("return4");
                    return;
                }
            }
        }

        //最高分相等,则优先进行进攻
        if( blackInfo.bestPoint == whiteInfo.bestPoint )    
        {
            if(color == 1) {
                int a[] = new int[20];
                for(int i = 0;i < whiteInfo.bestSum;i++)
                {
                    a[i] = point(best_w[i], 2);
                }
                int max_b = MAX(a, blackInfo.bestSum);
                for(int i = 0;i < whiteInfo.bestSum;i++)
                {
                    if(a[i] == max_b)
                    {
                        MyChessBoard.chess[best_w[i].x][best_w[i].y] = color;
                        MyChessBoard.record(best_w[i].x,best_w[i].y);

                        return;
                    }
                }
            }
            if(color == 2) {
                int a[] = new int[20];
                for(int i = 0;i < blackInfo.bestSum;i++)
                {
                    a[i] = point(best_b[i],1);
                }
                int max_w = MAX(a, blackInfo.bestSum);
                for(int i = 0;i < blackInfo.bestSum;i++)
                {
                    if(a[i] == max_w)
                    {
                        MyChessBoard.chess[best_b[i].x][best_b[i].y] = color;
                        MyChessBoard.record(best_b[i].x,best_b[i].y);
                //      System.out.println("return6");
                        return;
                    }
                }
            }

        }
    }

    //对某个颜色的棋子进行全局评估,放入分数数组
    private void wholePoints(int [][]points,int color){
        for( int i =0;i < 15;i++)
        {
            for(int j = 0;j < 15;j++)
            {
                position temp = new position(i,j);
                points[i][j] = point(temp,color);
            }
        }
    }

    //求数组最大值
    private int MAX(int[] a, int n) {

        int max = a[0];
        for(int i =1; i < n ;i++)
        {
            if(a[i] > max)
                max = a[i];
        }
        return max;
    }

    //给定位置,返回该点位的分数
    int point(position pos, int color)
    {
        if(MyChessBoard.chess[pos.x][pos.y] != 0)
        {
            return 0;
        }

        int sum = 0;

        sum += evaluateUp(pos, color);
        sum += evaluateLeft(pos, color);
        sum += evaluateLeftUp(pos, color);
        sum += evaluateRightUp(pos, color);

        return sum;
    }

    long evaluateUp(position pos, int color)
    {
        position p_i = new position(pos);
        int count = 0,mc = 1;
        boolean flag = true;
        int c_blank = 0;
        int judge_t;//记录颜色
        int blank = -1;

        try
        {
            do
            {
                p_i.up(p_i, flag);
                judge_t = MyChessBoard.chess[p_i.x][p_i.y];         //颜色
                if(judge_t == color)
                {
                    if(c_blank == 1)
                    {
                        count += 1;
                        mc++;
                    }
                    else
                    {
                        mc++;
                        if(mc == 5)
                            return 100000000000l;
                        count += 2;
                    }
                    blank = 0;
                }
                else 
                {
                    if(judge_t == 0)
                    {
                        if(c_blank >= 1)
                            flag = false;
                        else
                        {
                            c_blank++;
                        }
                        blank = 1;
                    }
                    else
                    {
                        count-=2;
                        flag = false;
                        if(blank == 1   || count < 0)
                            count+=2;
                        blank = 0;
                    }
                }
            }while(flag);
        }
        catch(Exception e)
        {
            flag = false;
            if(blank == 0)count-=2;
        }

        p_i.x = pos.x;
        p_i.y = pos.y;
        int b_blank = 0;//记录另一半的空白格子
        blank = -1;
        try
        {
            do
            {
                p_i.up(p_i, flag);
                judge_t = MyChessBoard.chess[p_i.x][p_i.y];
                if(judge_t == color)
                {
                    if(b_blank == 1)
                    {
                        count += 1;
                        mc++;
                    }
                    else
                    {
                        if(b_blank == 0)
                            mc++;
                        if(mc == 5)
                            return 100000000000L;
                        count += 2;
                    }
                    blank = 0;
                }
                else 
                {
                    if(judge_t == 0)
                    {
                    if(b_blank >= 1)
                            flag = true;
                        else
                        {
                            b_blank++;
                        }
                    blank = 1;
                    }
                    else
                    {
                        count-=2;
                        if(blank==1||(count<0&&mc==1))
                            count+=2;
                        flag = true;
                    }
                }
            }while(!flag);
        }
        catch(Exception e)
        {
            if(b_blank == 0)count-=2;
            return (long) Math.pow(10,count);
        }
        return (long) Math.pow(10,count);
    }
    long evaluateLeft(position pos, int color)
    {
        position p_i = new position(pos);
        int count = 0,mc = 1;
        boolean flag = true;
        int c_blank = 0;
        int judge_t;//记录颜色
        int blank = -1;

        try
        {
            do
            {
                p_i.left(p_i, flag);
                judge_t = MyChessBoard.chess[p_i.x][p_i.y];         //颜色
                if(judge_t == color)
                {
                    if(c_blank == 1)
                    {
                        count += 1;
                        mc++;
                    }
                    else
                    {
                        mc++;
                        if(mc == 5)
                            return 100000000000l;
                        count += 2;
                    }
                    blank = 0;
                }
                else 
                {
                    if(judge_t == 0)
                    {
                        if(c_blank >= 1)
                            flag = false;
                        else
                        {
                            c_blank++;
                        }
                        blank = 1;
                    }
                    else
                    {
                        count-=2;
                        flag = false;
                        if(blank == 1   || count < 0)
                            count+=2;
                        blank = 0;
                    }
                }
            }while(flag);
        }
        catch(Exception e)
        {
            flag = false;
            if(blank == 0)count-=2;
        }

        p_i.x = pos.x;
        p_i.y = pos.y;
        int b_blank = 0;//记录另一半的空白格子
        blank = -1;
        try
        {
            do
            {
                p_i.left(p_i, flag);
                judge_t = MyChessBoard.chess[p_i.x][p_i.y];
                if(judge_t == color)
                {
                    if(b_blank == 1)
                    {
                        count += 1;
                        mc++;
                    }
                    else
                    {
                        if(b_blank == 0)
                            mc++;
                        if(mc == 5)
                            return 100000000000L;
                        count += 2;
                    }
                    blank = 0;
                }
                else 
                {
                    if(judge_t == 0)
                    {
                    if(b_blank >= 1)
                            flag = true;
                        else
                        {
                            b_blank++;
                        }
                    blank = 1;
                    }
                    else
                    {
                        count-=2;
                        if(blank==1||(count<0&&mc==1))
                            count+=2;
                        flag = true;
                    }
                }
            }while(!flag);
        }
        catch(Exception e)
        {
            if(b_blank == 0)count-=2;
            return (long) Math.pow(10,count);
        }
        return (long) Math.pow(10,count);
    }
    long evaluateLeftUp(position pos, int color)
    {
        position p_i = new position(pos);
        int count = 0,mc = 1;
        boolean flag = true;
        int c_blank = 0;
        int judge_t;//记录颜色
        int blank = -1;

        try
        {
            do
            {
                p_i.leftUp(p_i, flag);
                judge_t = MyChessBoard.chess[p_i.x][p_i.y];         //颜色
                if(judge_t == color)
                {
                    if(c_blank == 1)
                    {
                        count += 1;
                        mc++;
                    }
                    else
                    {
                        mc++;
                        if(mc == 5)
                            return 100000000000l;
                        count += 2;
                    }
                    blank = 0;
                }
                else 
                {
                    if(judge_t == 0)
                    {
                        if(c_blank >= 1)
                            flag = false;
                        else
                        {
                            c_blank++;
                        }
                        blank = 1;
                    }
                    else
                    {
                        count-=2;
                        flag = false;
                        if(blank == 1   || count < 0)
                            count+=2;
                        blank = 0;
                    }
                }
            }while(flag);
        }
        catch(Exception e)
        {
            flag = false;
            if(blank == 0)count-=2;
        }

        p_i.x = pos.x;
        p_i.y = pos.y;
        int b_blank = 0;//记录另一半的空白格子
        blank = -1;
        try
        {
            do
            {
                p_i.leftUp(p_i, flag);
                judge_t = MyChessBoard.chess[p_i.x][p_i.y];
                if(judge_t == color)
                {
                    if(b_blank == 1)
                    {
                        count += 1;
                        mc++;
                    }
                    else
                    {
                        if(b_blank == 0)
                            mc++;
                        if(mc == 5)
                            return 100000000000L;
                        count += 2;
                    }
                    blank = 0;
                }
                else 
                {
                    if(judge_t == 0)
                    {
                    if(b_blank >= 1)
                            flag = true;
                        else
                        {
                            b_blank++;
                        }
                    blank = 1;
                    }
                    else
                    {
                        count-=2;
                        if(blank==1||(count<0&&mc==1))
                            count+=2;
                        flag = true;
                    }
                }
            }while(!flag);
        }
        catch(Exception e)
        {
            if(b_blank == 0)count-=2;
            return (long) Math.pow(10,count);
        }
        return (long) Math.pow(10,count);
    }
    long evaluateRightUp(position pos, int color)
    {
        position p_i = new position(pos);
        int count = 0,mc = 1;
        boolean flag = true;
        int c_blank = 0;
        int judge_t;//记录颜色
        int blank = -1;

        try
        {
            do
            {
                p_i.rightUp(p_i, flag);
                judge_t = MyChessBoard.chess[p_i.x][p_i.y];         //颜色
                if(judge_t == color)
                {
                    if(c_blank == 1)
                    {
                        count += 1;
                        mc++;
                    }
                    else
                    {
                        mc++;
                        if(mc == 5)
                            return 100000000000l;
                        count += 2;
                    }
                    blank = 0;
                }
                else 
                {
                    if(judge_t == 0)
                    {
                        if(c_blank >= 1)
                            flag = false;
                        else
                        {
                            c_blank++;
                        }
                        blank = 1;
                    }
                    else
                    {
                        count-=2;
                        flag = false;
                        if(blank == 1   || count < 0)
                            count+=2;
                        blank = 0;
                    }
                }
            }while(flag);
        }
        catch(Exception e)
        {
            flag = false;
            if(blank == 0)count-=2;
        }

        p_i.x = pos.x;
        p_i.y = pos.y;
        int b_blank = 0;//记录另一半的空白格子
        blank = -1;
        try
        {
            do
            {
                p_i.rightUp(p_i, flag);
                judge_t = MyChessBoard.chess[p_i.x][p_i.y];
                if(judge_t == color)
                {
                    if(b_blank == 1)
                    {
                        count += 1;
                        mc++;
                    }
                    else
                    {
                        if(b_blank == 0)
                            mc++;
                        if(mc == 5)
                            return 100000000000L;
                        count += 2;
                    }
                    blank = 0;
                }
                else 
                {
                    if(judge_t == 0)
                    {
                    if(b_blank >= 1)
                            flag = true;
                        else
                        {
                            b_blank++;
                        }
                    blank = 1;
                    }
                    else
                    {
                        count-=2;
                        if(blank==1||(count<0&&mc==1))
                            count+=2;
                        flag = true;
                    }
                }
            }while(!flag);
        }
        catch(Exception e)
        {
            if(b_blank == 0)count-=2;
            return (long) Math.pow(10,count);
        }
        return (long) Math.pow(10,count);
    }

    //给出分数数组,找出最大值对应的位置(可能不止一个),返回分数最大值
    void best_posits(int points[][], position p_s[], BestInfo colorInfo)
    {
        int max_row[] = new int[15];
        //找出最大值
        for(int i = 0;i < 15;i++)
            max_row[i] = MAX(points[i],15);
        colorInfo.bestPoint = MAX(max_row,15);

        //找出最大值对应的位置,并统计最大值的个数
        colorInfo.bestSum = 0;
        for(int i = 0;i < 15;i++)
        {
            for(int j =0;j < 15;j++)
            {
                if(points[i][j] == colorInfo.bestPoint)
                {
                    p_s[colorInfo.bestSum] = new position(i,j);
                    colorInfo.bestSum++;
                }
            }
        }
    //  System.out.println("count = "+colorInfo.bestSum);
        return;
    }

}
class position{
    public  int x,y;
    public position(int x,int y){
        this.x = x;
        this.y = y;
    }
    public position(position p){
        x = p.x;
        y = p.y;
    }
    public boolean equals(position p) {
        if(x == p.x && y == p.y)
            return true;
        else
            return false;
    }
    public position up(position p,boolean flag) {
        if(flag)
            p.y = p.y - 1;
        else
            p.y =p.y + 1;
        return p;
    }
    public position left(position p,boolean flag) {
        if(flag)
            p.x = p.x - 1;
        else
            p.x =p.x + 1;
        return p;
    }
    public position leftUp(position p,boolean flag) {
        return up(left(p,flag),flag);
    }
    public position rightUp(position p,boolean flag) {
        return up(left(p,!flag),flag);
    }
}

最后,再加入一个main函数类,运行即可:

package renju;

public class renju {

    public static void main(String[] args) {
        // TODO 自动生成的方法存根
        ChessGame myRenju = new ChessGame();
        myRenju.play();
    }

}

猜你喜欢

转载自blog.csdn.net/black_kyatu/article/details/79372421