如何实现Minimax Alpha-Beta算法的国际象棋引擎自对弈?
Alright, let's get your chess engine duking it out against itself! Right now your code is built for human vs computer play, so we just need to adjust the flow to remove human input and have both sides use your Alpha-Beta AI. Here's a step-by-step solution tailored to your existing code:
First, let's encapsulate the self-play logic in a separate method to keep your code clean and modular. Add this to your Main class:
private static void startComputerVsComputer(JFrame frame, GUInterface gui) { // Loop until the game ends (checkmate or stalemate) while (true) { // White AI makes a move (assuming 0 = white player in your AlphaBeta logic) long startTime = System.currentTimeMillis(); Move whiteMove = AlphaBeta.alphaBeta(ABChess.gameDepth, 1000000, -1000000, new Move(), 0); long endTime = System.currentTimeMillis(); ABChess.makeMove(whiteMove); String moveLog = String.format("White's move took %.2f seconds", (endTime - startTime)/1000.0); System.out.println(moveLog); displayMessage(moveLog); frame.repaint(); // Check if white's move ended the game if (isGameOver()) { handleGameEnd(); break; } // Flip board (matches your existing logic for player perspective) ABChess.flipBoard(); // Black AI makes a move (use 1 for black player - confirm this matches your AlphaBeta parameter!) startTime = System.currentTimeMillis(); Move blackMove = AlphaBeta.alphaBeta(ABChess.gameDepth, 1000000, -1000000, new Move(), 1); endTime = System.currentTimeMillis(); ABChess.makeMove(blackMove); moveLog = String.format("Black's move took %.2f seconds", (endTime - startTime)/1000.0); System.out.println(moveLog); displayMessage(moveLog); frame.repaint(); // Check if black's move ended the game if (isGameOver()) { handleGameEnd(); break; } // Flip board back for next white turn ABChess.flipBoard(); // Add a small delay so you can follow the moves (adjust as needed) try { Thread.sleep(1000); // 1 second pause between moves } catch (InterruptedException e) { e.printStackTrace(); } } } // Helper method to check if the game has ended private static boolean isGameOver() { boolean isCheckmate = !ABChess.kingSafe(); boolean isStalemate = ABChess.possibleMoves().isEmpty() && ABChess.kingSafe(); return isCheckmate || isStalemate; } // Helper method to handle post-game logic private static void handleGameEnd() { String message; if (!ABChess.kingSafe()) { message = "Checkmate! Game over!"; } else { message = "Stalemate! Game ended in a draw."; } int playAgain = JOptionPane.showOptionDialog( null, message + "\nWanna play again?", "Game Over", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, null, ABChess.choice, ABChess.choice[1] ); if (playAgain == 0) { ABChess.resetGame(); // Restart self-play if user chooses to startComputerVsComputer((JFrame) SwingUtilities.getWindowAncestor(textField), new GUInterface()); } else { System.exit(0); } }
Modify your main method to let users pick between human vs computer and computer vs computer play. Replace the existing player choice dialog with this:
// Let user select game mode String[] gameModes = {"Human vs Computer", "Computer vs Computer"}; int modeChoice = JOptionPane.showOptionDialog( null, "Choose your game mode:", "Chess Engine Mode", JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, gameModes, gameModes[0] ); if (modeChoice == 1) { // Start computer vs computer play startComputerVsComputer(frame, gui); } else { // Keep your existing human vs computer logic here 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"); } }
If you want to keep human vs computer functionality, add a check in your mouseReleased method to only run human input logic when in human vs computer mode. For example, add a static boolean flag in ABChess like public static boolean isSelfPlay = false;, then wrap your mouse logic:
public void mouseReleased(MouseEvent event) { if (ABChess.isSelfPlay) return; // Skip human input during self-play // Your existing mouse input logic here... }
Don't forget to set ABChess.isSelfPlay = true; inside the startComputerVsComputer method, and false when starting human vs computer play.
- Double-check that the final parameter in
AlphaBeta.alphaBeta()correctly represents the player (0 for white, 1 for black). If your AI uses a different convention, adjust this value for black's turn. - Confirm that
ABChess.kingSafe()andABChess.possibleMoves()accurately detect checkmate and stalemate—these are critical for ending the self-play loop correctly. - The 1-second delay between moves is optional; adjust it to make the game faster or slower depending on how you want to observe the AI's play.
内容的提问来源于stack exchange,提问作者Jordan Oguns

