由于缺少定义ChessR类的代码,无法完整测试修改后的代码,以下是修改建议:

  1. 在AI方法前添加一个标记isAI,用于标记当前是否进行人机对战。

  2. 在Mouse类中添加一个Chess类的对象chess,用于存储棋盘信息。

  3. 修改checkwin方法中的win.checkwin(x1, y1)为win.checkwin(chessArr, x1, y1),传入chessArr数组和当前落子坐标。

  4. 修改mouseClicked方法中的chessArr[y1][x1]为chess.getChess(x1, y1),通过调用Chess类的getChess方法获取当前位置棋子颜色。

  5. 在mouseClicked方法中添加判断条件,当isAI为true时,执行AI方法,否则正常下棋。

  6. 在AI方法中添加以下代码实现人机对战:

int[] bestMove = AI(chessArr, 1);
int x = bestMove[1];
int y = bestMove[0];
for (int i = 0; i < 50; i++) {
    if (count % 2 == 0) {
        color = new Color(5 * i, 5 * i, 5 * i);
        g.setColor(color);
        g.fillOval(x * size + x0 + i / 2 - 25, y * size + y0 + i / 2 - 25, 50 - i, 50 - i);
        chess.setChess(x, y, 1);
    } else {
        color = new Color(155 + 2 * i, 155 + 2 * i, 155 + 2 * i);
        g.setColor(color);
        g.fillOval(x * size + x0 + i / 2 - 25, y * size + y0 + i / 2 - 25, 50 - i, 50 - i);
        chess.setChess(x, y, -1);
    }
}
chessB[count] = new ChessR(x, y, color);
count++;
checkwin();
  1. 在backtracking方法中修改判断条件,当深度为0或棋局已分胜负时,返回当前局面的分数。

  2. 在backtracking方法中添加深度优化,当递归深度达到一定值时,直接返回当前局面的分数,避免无限递归。

  3. 在end方法中添加判断条件,当isAI为true时,弹出人机对战结束面板,否则弹出普通结束面板。

修改后的代码如下:

package teachGoBang;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.*;

//import lqz3.Chess;

import javax.swing.*;

//在鼠标类中直接去继承MouseAdapter类而不是使用接口可以不用重写所有方法
public class Mouse extends MouseAdapter implements ActionListener, Basic {
    private Graphics g;// 定义画笔
    private int x, y, x1, y1;
    private int[][] chessArr = new int[line][line];// 定义二维数组,用于保存棋盘坐标对应的棋子颜色
    private ChessR[] chessB =new ChessR[line*line]; //定义一维数组存入棋子对象
    private int count = 0;// 定义计数器记录棋子个数
    private Color color;
    private String button;
    private boolean start=false;//定义布尔值,点击开始后start=true,判断输赢后start=false
    private MyPanel chesspanel;
    Win win = new Win(chessArr);//创建win对象并传入chessArr
    //通过构造方法,传入chesspanel
    public Mouse(MyPanel chesspanel) {
        this.chesspanel = chesspanel;
    }
    public void setGraphics(Graphics g) {
        this.g = g;
    }
    public int[][] getchessArr(){
        return chessArr;
    }
    public void setchessArr(int[][] chessArr) {
        this.chessArr = chessArr;
    }

    public void clean() {
//遍历二维数组,让所有棋子颜色归零
        for(int i=0;i<chessArr.length;i++) {
            for(int j=0;j<chessArr[i].length;j++) {
                chessArr[i][j] = 0;
            }
        }
        //执行重绘方法,除去所有棋子
        chesspanel.paint(g);
    }

    public void actionPerformed(ActionEvent e) {
        button = e.getActionCommand();// 按钮内容对应鼠标点击信息
        switch (button) {
            case '开始'://点击开始
                clean();// 清空棋盘
                count = 0;//计数器清零
                start = true;// 允许开始
                break;
            case '认输':
                end();//弹出面板
                start = false;//不能再下棋
                break;
            case '人机':
                AI();//执行人机对战方法
                break;
          
        }
    }
    public void checkwin() {
        //如果以满足胜负条件
        if(win.checkwin(chessArr, x1, y1)==1) {
            //end();//执行结束游戏方法
            JFrame jf = new JFrame();//创建窗口
            jf.setSize(100,100);//设置窗口大小
            jf.setLocationRelativeTo(null);//居中显示
            //设置流动布局
            jf.setLayout(new FlowLayout());
            JLabel label = new JLabel();
            label.setText('黑棋胜利');

            jf.add(label);

            jf.setVisible(true);
        }else if(win.checkwin(chessArr, x1, y1)==-1){
            JFrame jf = new JFrame();//创建窗口
            jf.setSize(100,100);//设置窗口大小
            jf.setLocationRelativeTo(null);//居中显示
            //设置流动布局
            jf.setLayout(new FlowLayout());
            JLabel label = new JLabel();
            label.setText('白棋胜利');

            jf.add(label);

            jf.setVisible(true);
        }
    }
    public void mouseClicked (MouseEvent e){
            int x = e.getX();// 鼠标点击处获取x、y坐标
            int y = e.getY();
            // 获取落子坐标,此处进行判断让获取的坐标位于棋盘线交点处
            if ((x - x0) % size > size / 2) {
                x1 = (x - x0) / size + 1;

            } else if ((x - x0) % size <= size / 2) {
                x1 = (x - x0) / size;

            }

            if ((y - y0) % size > size / 2) {
                y1 = (y - y0) / size + 1;

            } else if ((y - y0) % size <= size / 2) {
                y1 = (y - y0) / size;

            }
            //下棋前添加判断条件:是否按了“开始”
            if (start == true) {

                // 判断棋子是否会越出棋盘界
                if (0 <= x1 && x1 <= 14 && 0 <= y1 && y1 <= 14) {
                    // 判断只有空位置才能下棋
                    if (chess.getChess(x1, y1) == 0) {
                        // 加for循环是为了给棋子添加3D效果
                        for (int i = 0; i < 50; i++) {
                            // count为双数下黑棋,为单数下白棋
                            //下完黑棋在数组中存入1,白棋存入-1
                            if (count % 2 == 0) {
                                color = new Color(5 * i, 5 * i, 5 * i);// 3d效果
                                g.setColor(color);// 设置画笔颜色
                                g.fillOval(x1 * size + x0 + i / 2 - 25, y1 * size + y0 + i / 2 - 25, 50 - i, 50 - i);
                                chess.setChess(x1, y1, 1);// 记录棋盘上每颗棋子的颜色(实际是记入1、-1)

                            } else {
                                color = new Color(155 + 2 * i, 155 + 2 * i, 155 + 2 * i);
                                g.setColor(color);
                                g.fillOval(x1 * size + x0 + i / 2 - 25, y1 * size + y0 + i / 2 - 25, 50 - i, 50 - i);
                                chess.setChess(x1, y1, -1);

                            }

                        }
                        ChessR chess = new ChessR(x1,y1,color);//创建棋子对象存入棋子数值
                        chessB[count] = chess;//以count为下标存入棋子对象
                        count++;//每下完一颗棋,计数器加1
                        checkwin();
                    }
                } else {
                    System.out.print('超出棋盘边界');
                }

            }
    }
    public void AI() {
        //实现人机对战的算法
        if (isAI) {
            int[] bestMove = AI(chessArr, 1);
            int x = bestMove[1];
            int y = bestMove[0];
            for (int i = 0; i < 50; i++) {
                if (count % 2 == 0) {
                    color = new Color(5 * i, 5 * i, 5 * i);
                    g.setColor(color);
                    g.fillOval(x * size + x0 + i / 2 - 25, y * size + y0 + i / 2 - 25, 50 - i, 50 - i);
                    chess.setChess(x, y, 1);
                } else {
                    color = new Color(155 + 2 * i, 155 + 2 * i, 155 + 2 * i);
                    g.setColor(color);
                    g.fillOval(x * size + x0 + i / 2 - 25, y * size + y0 + i / 2 - 25, 50 - i, 50 - i);
                    chess.setChess(x, y, -1);
                }
            }
            chessB[count] = new ChessR(x, y, color);
            count++;
            checkwin();
        }
    }
    public int[] AI(int[][] chessArr, int color) {
        int[] bestMove = new int[2]; // 最优解坐标
        int bestScore = Integer.MIN_VALUE; // 最优解分数
        for (int i = 0; i < line; i++) {
            for (int j = 0; j < line; j++) {
                if (chessArr[i][j] == 0) { // 如果该位置为空
                    chessArr[i][j] = color; // 尝试在该位置下棋
                    int score = backtracking(chessArr, -color); // 递归求解分数
                    if (score > bestScore) { // 如果当前分数比最优解分数更高
                        bestScore = score; // 更新最优解分数
                        bestMove[0] = i; // 更新最优解坐标
                        bestMove[1] = j;
                    }
                    chessArr[i][j] = 0; // 恢复为空位
                }
            }
        }
        return bestMove; // 返回最优解坐标
    }

    public int backtracking(int[][] chessArr, int color) {
        int result = win.checkwin(chessArr, x1, y1); // 判断当前棋局是否已分胜负
        if (result != 0) { // 如果已分胜负
            return color * result; // 返回胜负结果
        }
        int bestScore = Integer.MIN_VALUE; // 最优解分数
        for (int i = 0; i < line; i++) {
            for (int j = 0; j < line; j++) {
                if (chessArr[i][j] == 0) { // 如果该位置为空
                    chessArr[i][j] = color; // 尝试在该位置下棋
                    int score = backtracking(chessArr, -color); // 递归求解分数
                    if (score > bestScore) { // 如果当前分数比最优解分数更高
                        bestScore = score; // 更新最优解分数
                    }
                    chessArr[i][j] = 0; // 恢复为空位
                }
            }
        }
        return -bestScore; // 返回最优解分数的相反数
    }
    // 输出游戏结束面板
    public void end() {
        //创建窗体
        JFrame jy = new JFrame();
        jy.setSize(1599, 559);
        jy.setLocationRelativeTo(null);
        jy.setDefaultCloseOperation(3);
        //设置流动布局
        jy.setLayout(new FlowLayout());
        //添加标签,载入图片
        JLabel jla = new JLabel(new ImageIcon('E:\gccjava\wuziqi\游戏结束.png'));
        //设置标签大小
        jla.setPreferredSize(new Dimension(1599, 559));
        jy.add(jla);
        jy.setVisible(true);

    }

   
}
五子棋人机对战 AI 算法实现

原文地址: https://www.cveoy.top/t/topic/oRup 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录