Implemented game restarting
+ Restarting method in Game + Abstract cancelMove method in Player + Stopping calculations in AIPlayer when the game has been restarted
This commit is contained in:
parent
fe8ae1826e
commit
a3b5531f09
@ -29,10 +29,6 @@ public class Game {
|
||||
players.values().forEach(player -> player.setGame(this));
|
||||
}
|
||||
|
||||
public void start() {
|
||||
players.get(Color.WHITE).requestMove();
|
||||
}
|
||||
|
||||
public void onMove(Player player, Move move) {
|
||||
if (board.getPos(move).getColor() == player.color && board.attemptMove(move)) {
|
||||
System.out.printf("%s: %s%n", player.color, move);
|
||||
@ -51,4 +47,15 @@ public class Game {
|
||||
}
|
||||
} else player.requestMove();
|
||||
}
|
||||
|
||||
public void start() {
|
||||
players.get(Color.WHITE).requestMove();
|
||||
}
|
||||
|
||||
public void restart() {
|
||||
players.forEach((k, v) -> v.cancelMove());
|
||||
board.initializeDefaultPositions();
|
||||
boardComponent.repaint();
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
@ -61,4 +61,9 @@ public class NaturalPlayer extends Player {
|
||||
public void requestMove() {
|
||||
moveRequested = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelMove() {
|
||||
moveRequested = false;
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ public abstract class Player {
|
||||
|
||||
public abstract void requestMove();
|
||||
|
||||
public abstract void cancelMove();
|
||||
|
||||
public Game getGame() { return game; }
|
||||
|
||||
public void setGame(Game game) { this.game = game; }
|
||||
|
@ -6,6 +6,7 @@ import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
@ -25,14 +26,19 @@ public class AIPlayer extends Player {
|
||||
private int availableProcessors;
|
||||
private int maxDepth;
|
||||
|
||||
private volatile boolean exitRequested;
|
||||
private volatile ExecutorService executor;
|
||||
|
||||
public AIPlayer(Board board, Color color, int maxDepth) {
|
||||
super(board, color);
|
||||
availableProcessors = Runtime.getRuntime().availableProcessors();
|
||||
this.maxDepth = maxDepth;
|
||||
exitRequested = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestMove() {
|
||||
exitRequested = false;
|
||||
/*
|
||||
* Define some processing threads, split the available moves between them and
|
||||
* retrieve the result after their execution.
|
||||
@ -63,7 +69,7 @@ public class AIPlayer extends Player {
|
||||
/*
|
||||
* Execute processors, get the best result and pass it back to the Game class
|
||||
*/
|
||||
ExecutorService executor = Executors.newFixedThreadPool(numThreads);
|
||||
executor = Executors.newFixedThreadPool(numThreads);
|
||||
List<ProcessingResult> results = new ArrayList<>(numThreads);
|
||||
try {
|
||||
List<Future<ProcessingResult>> futures = executor.invokeAll(processors);
|
||||
@ -74,7 +80,18 @@ public class AIPlayer extends Player {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
results.sort((r1, r2) -> Integer.compare(r2.score, r1.score));
|
||||
SwingUtilities.invokeLater(() -> game.onMove(this, results.get(0).move));
|
||||
if (!exitRequested) SwingUtilities.invokeLater(() -> game.onMove(this, results.get(0).move));
|
||||
}, "AIPlayer calculation setup").start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelMove() {
|
||||
exitRequested = true;
|
||||
executor.shutdownNow();
|
||||
try {
|
||||
executor.awaitTermination(500, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,10 +26,16 @@ public class GameModeDialog extends JDialog {
|
||||
|
||||
private static final long serialVersionUID = 5470026233924735607L;
|
||||
|
||||
private final MainWindow parent;
|
||||
private final Board board;
|
||||
private final OverlayComponent overlayComponent;
|
||||
private final BoardComponent boardComponent;
|
||||
private final Map<Color, Player> players;
|
||||
|
||||
/**
|
||||
* Create the dialog.
|
||||
*/
|
||||
public GameModeDialog(BoardPane boardPane) {
|
||||
public GameModeDialog(MainWindow parent, BoardPane boardPane) {
|
||||
super();
|
||||
setModal(true);
|
||||
setTitle("Game Mode Selection");
|
||||
@ -46,40 +52,43 @@ public class GameModeDialog extends JDialog {
|
||||
}
|
||||
});
|
||||
|
||||
final BoardComponent boardComponent = boardPane.getBoardComponent();
|
||||
final OverlayComponent overlayComponent = boardPane.getOverlayComponent();
|
||||
final Board board = boardComponent.getBoard();
|
||||
this.parent = parent;
|
||||
boardComponent = boardPane.getBoardComponent();
|
||||
overlayComponent = boardPane.getOverlayComponent();
|
||||
board = boardComponent.getBoard();
|
||||
players = new HashMap<>();
|
||||
|
||||
JButton btnNatural = new JButton("Game against natural opponent");
|
||||
btnNatural.addActionListener((evt) -> {
|
||||
Map<Color, Player> players = new HashMap<>();
|
||||
players.put(Color.WHITE, new NaturalPlayer(board, Color.WHITE, overlayComponent));
|
||||
players.put(Color.BLACK, new NaturalPlayer(board, Color.BLACK, overlayComponent));
|
||||
new Game(players, boardComponent).start();
|
||||
dispose();
|
||||
startGame();
|
||||
});
|
||||
getContentPane().add(btnNatural);
|
||||
|
||||
JButton btnAI = new JButton("Game against AI");
|
||||
btnAI.addActionListener((evt) -> {
|
||||
Map<Color, Player> players = new HashMap<>();
|
||||
players.put(Color.WHITE, new NaturalPlayer(board, Color.WHITE, overlayComponent));
|
||||
players.put(Color.BLACK, new AIPlayer(board, Color.BLACK, 5));
|
||||
new Game(players, boardComponent).start();
|
||||
dispose();
|
||||
startGame();
|
||||
});
|
||||
getContentPane().add(btnAI);
|
||||
|
||||
JButton btnAI2 = new JButton("AI against AI");
|
||||
btnAI2.addActionListener((evt) -> {
|
||||
Map<Color, Player> players = new HashMap<>();
|
||||
players.put(Color.WHITE, new AIPlayer(board, Color.WHITE, 5));
|
||||
players.put(Color.BLACK, new AIPlayer(board, Color.BLACK, 4));
|
||||
new Game(players, boardComponent).start();
|
||||
dispose();
|
||||
startGame();
|
||||
});
|
||||
getContentPane().add(btnAI2);
|
||||
|
||||
setLocationRelativeTo(null);
|
||||
}
|
||||
|
||||
private void startGame() {
|
||||
Game game = new Game(players, boardComponent);
|
||||
parent.setGame(game);
|
||||
game.start();
|
||||
dispose();
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import dev.kske.chess.board.Board;
|
||||
|
||||
import dev.kske.chess.game.Game;
|
||||
|
||||
/**
|
||||
* Project: <strong>Chess</strong><br>
|
||||
@ -19,6 +19,7 @@ import dev.kske.chess.board.Board;
|
||||
public class MainWindow {
|
||||
|
||||
private JFrame mframe;
|
||||
private Game game;
|
||||
|
||||
/**
|
||||
* Launch the application.
|
||||
@ -61,12 +62,16 @@ public class MainWindow {
|
||||
mframe.getContentPane().add(toolPanel, BorderLayout.NORTH);
|
||||
|
||||
JButton btnRestart = new JButton("Restart");
|
||||
btnRestart.addActionListener((evt) -> System.err.println("Resetting not implemented!"));
|
||||
btnRestart.addActionListener((evt) -> { if (game != null) game.restart(); });
|
||||
toolPanel.add(btnRestart);
|
||||
mframe.pack();
|
||||
mframe.setLocationRelativeTo(null);
|
||||
|
||||
// Display dialog for game mode selection
|
||||
new GameModeDialog(boardPane).setVisible(true);
|
||||
new GameModeDialog(this, boardPane).setVisible(true);
|
||||
}
|
||||
|
||||
public Game getGame() { return game; }
|
||||
|
||||
public void setGame(Game game) { this.game = game; }
|
||||
}
|
||||
|
Reference in New Issue
Block a user