如何让Minimax Alpha Beta算法发挥自己的作用?
How to make Minimax Alpha Beta algorithm play itself?
我已经开发了一个带有 minimax 和 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);
}
}
}
}
}
这是每次松开鼠标时调用算法的地方。不知道如何编码到它用白色棋子而不是我自己演奏的地方。
我通常会将 Player 与 Game 分开,而 Game 会请求来自 Player 对象的交互。 Player 对象要么是人类(因此所需的输入被委托给某些 UI),要么是 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
并调用模拟方法。那时你也可以决定完全跳过 UI 演示(这样学习会更快)。
我已经开发了一个带有 minimax 和 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);
}
}
}
}
}
这是每次松开鼠标时调用算法的地方。不知道如何编码到它用白色棋子而不是我自己演奏的地方。
我通常会将 Player 与 Game 分开,而 Game 会请求来自 Player 对象的交互。 Player 对象要么是人类(因此所需的输入被委托给某些 UI),要么是 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
并调用模拟方法。那时你也可以决定完全跳过 UI 演示(这样学习会更快)。