如何让极小化-极大化 Alpha-Beta 算法自我对弈?

我已经开发了一个使用极小化-极大化和 Alpha-Beta 剪枝的可工作的国际象棋引擎,但是我想通过让算法自我对弈来测试它,即电脑对电脑。我尝试了各种方法但都没有成功。不知道该如何实现这个功能?

public class Main {  static JTextArea textField;    public static void main(String[] args) {        while ( 'K' != ABChess.board[ABChess.kingLocationUU/8][ABChess.kingLocationUU%8]) {ABChess.kingLocationUU++;}        while ( 'k' != ABChess.board[ABChess.kingLocationLL/8][ABChess.kingLocationLL%8]) {ABChess.kingLocationLL++;}        Asset.init("/images/ChessPiecess.png");        ABChess.updateKingLocations();        //print();          JPanel depthPanel = depthPanel();        JPanel optionPanel = optionPanel();        JPanel logPanel = logPanel();        JPanel menuPanel = new JPanel();        menuPanel.setPreferredSize(new Dimension(140, 100));        menuPanel.setLayout(new BoxLayout(menuPanel, BoxLayout.Y_AXIS));        menuPanel.add(depthPanel);        menuPanel.add(optionPanel);        menuPanel.add(logPanel);        GUInterface gui = new GUInterface();        JPanel panel = new JPanel(new BorderLayout());        panel.add(gui);        panel.add(menuPanel, BorderLayout.EAST);        JFrame frame = new JFrame(ABChess.title);        frame.setSize(ABChess.width, ABChess.height);        frame.add(panel);        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        frame.setResizable(true);        frame.setLocationRelativeTo(null);        frame.setVisible(true);                System.out.println(ABChess.possibleMoves());        ABChess.playerChoice = JOptionPane.showOptionDialog(null, "Who wants to make the first move?", "Who moves first?", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, ABChess.options, ABChess.options[0]);        if (ABChess.playerChoice == 0){            ABChess.flipBoard();            long startTime=System.currentTimeMillis();            Move autoMove = AlphaBeta.alphaBeta(ABChess.gameDepth, 1000000, -1000000, new Move(), 0);            long endTime=System.currentTimeMillis();            ABChess.makeMove(autoMove);            ABChess.flipBoard();            System.out.println("COMPUTER'S MOVE TOOK "+((endTime-startTime)/1000.0)+" SECONDS");                                    ABChess.printBoard();            frame.repaint();            displayMessage("Took "+((endTime-startTime)/1000.0)+" seconds");        }    }

这是运行文件时对算法的初始调用。

public void mousePressed(MouseEvent event) {        if ( event.getX() < 8*sizeOfSquare && event.getY() < 8*sizeOfSquare) {            mouseX = event.getX();            mouseY = event.getY();            repaint();        }    }    public void mouseReleased(MouseEvent event) {        if  (event.getX() < 8*sizeOfSquare && event.getY() < 8*sizeOfSquare) {            newMouseX = event.getX();            newMouseY = event.getY();            if (event.getButton() == MouseEvent.BUTTON1) {                // Regular move                Move legalMovesMove = new Move(mouseY/sizeOfSquare, mouseX/sizeOfSquare, newMouseY/sizeOfSquare, newMouseX/sizeOfSquare, Test6.board[newMouseY/sizeOfSquare][newMouseX/sizeOfSquare]);                java.util.List<Move> legalMoves = ABChess.possibleMoves();                for(Move m : legalMoves) {                    if (m.equals(legalMovesMove)) {                        ABChess.makeMove(legalMovesMove);                        ABChess.flipBoard();                        long startTime=System.currentTimeMillis();                        Move autoMove = AlphaBeta.alphaBeta(ABChess.gameDepth, 1000000, -1000000, new Move(), 0);                        long endTime=System.currentTimeMillis();                        ABChess.makeMove(autoMove);                        ABChess.flipBoard();                        System.out.println("COMPUTER'S MOVE TOOK "+((endTime-startTime)/1000.0)+" SECONDS");                                                ABChess.printBoard();                        repaint();                    }                }                checkMate = ABChess.kingSafe();                if(checkMate == false){                   int yes = JOptionPane.showOptionDialog(null, "Do you want to make the first move?", "Who moves first?", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, JOptionPane.YES_OPTION);                   if (yes == JOptionPane.YES_OPTION){                       ABChess.resetGame();                        repaint();                   } else if (yes == JOptionPane.NO_OPTION){                              System.exit(0);                     }                }                legalMoves = ABChess.possibleMoves();                if (legalMoves.size() == 0) {                    ABChess.playAgain = JOptionPane.showOptionDialog(null, "Stalemate! Wanna play again?", "Draw!", JOptionPane.YES_NO_OPTION,                            JOptionPane.QUESTION_MESSAGE, null, ABChess.choice, ABChess.choice[1]);                    if (ABChess.playAgain == 0) {                        System.out.println("Yes I will");                        ABChess.resetGame();                        repaint();                    } else {                        System.exit(0);                    }                }            }        }    }

这是每次释放鼠标时调用算法的地方。不确定如何编写代码让它使用白棋自我对弈而不是我来操作。


回答:

通常我会将玩家和游戏分开,游戏会向玩家对象请求交互。玩家对象可以是人类(因此所需的输入会委托给某个用户界面),也可以是AI(因此会委托给某个实现来决定最佳移动)。

我建议使用对象来表示ABChess游戏,而不是使用静态方法。

因此,通过一些重构和将UI与逻辑分离,代码可能会像这样:

interface Player {    Move decide(List<Move> legalMoves);}class ChessGame {    ABChess game;    Player player1;    Player player2;    UIInterface ui;    ChessGame(Player player1, Player player2, UIInterface ui) {        this.player1 = player1;        this.player2 = player2;        this.ui = ui;        game = ...    }    public void simulate() {        // ... initial ui ...        boolean player1Turn = true;        do {            Move move = null;            if (player1Turn) {                move = player1.decide(game.possibleMoves());            } else {                move = player2.decide(game.possibleMoves());            }            game.makeMove(move);            // ... update ui ...            player1Turn = !player1Turn;        // check if somebody has won ...        } while (game.isRunning());        // ... update ui with the game result ...    }}

一旦完成这些,模拟游戏就变得简单了。你只需要用适当的玩家初始化ChessGame并调用simulate方法。此时,你也可以决定完全跳过UI展示(这样学习速度会更快)。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注