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));
|
players.values().forEach(player -> player.setGame(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start() {
|
|
||||||
players.get(Color.WHITE).requestMove();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onMove(Player player, Move move) {
|
public void onMove(Player player, Move move) {
|
||||||
if (board.getPos(move).getColor() == player.color && board.attemptMove(move)) {
|
if (board.getPos(move).getColor() == player.color && board.attemptMove(move)) {
|
||||||
System.out.printf("%s: %s%n", player.color, move);
|
System.out.printf("%s: %s%n", player.color, move);
|
||||||
@ -51,4 +47,15 @@ public class Game {
|
|||||||
}
|
}
|
||||||
} else player.requestMove();
|
} 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() {
|
public void requestMove() {
|
||||||
moveRequested = true;
|
moveRequested = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancelMove() {
|
||||||
|
moveRequested = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,8 @@ public abstract class Player {
|
|||||||
|
|
||||||
public abstract void requestMove();
|
public abstract void requestMove();
|
||||||
|
|
||||||
|
public abstract void cancelMove();
|
||||||
|
|
||||||
public Game getGame() { return game; }
|
public Game getGame() { return game; }
|
||||||
|
|
||||||
public void setGame(Game game) { this.game = 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.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
|
|
||||||
@ -25,14 +26,19 @@ public class AIPlayer extends Player {
|
|||||||
private int availableProcessors;
|
private int availableProcessors;
|
||||||
private int maxDepth;
|
private int maxDepth;
|
||||||
|
|
||||||
|
private volatile boolean exitRequested;
|
||||||
|
private volatile ExecutorService executor;
|
||||||
|
|
||||||
public AIPlayer(Board board, Color color, int maxDepth) {
|
public AIPlayer(Board board, Color color, int maxDepth) {
|
||||||
super(board, color);
|
super(board, color);
|
||||||
availableProcessors = Runtime.getRuntime().availableProcessors();
|
availableProcessors = Runtime.getRuntime().availableProcessors();
|
||||||
this.maxDepth = maxDepth;
|
this.maxDepth = maxDepth;
|
||||||
|
exitRequested = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void requestMove() {
|
public void requestMove() {
|
||||||
|
exitRequested = false;
|
||||||
/*
|
/*
|
||||||
* Define some processing threads, split the available moves between them and
|
* Define some processing threads, split the available moves between them and
|
||||||
* retrieve the result after their execution.
|
* retrieve the result after their execution.
|
||||||
@ -41,8 +47,8 @@ public class AIPlayer extends Player {
|
|||||||
/*
|
/*
|
||||||
* Get a copy of the board and the available moves.
|
* Get a copy of the board and the available moves.
|
||||||
*/
|
*/
|
||||||
Board board = (Board) AIPlayer.this.board.clone();
|
Board board = (Board) AIPlayer.this.board.clone();
|
||||||
List<Move> moves = board.getMoves(color);
|
List<Move> moves = board.getMoves(color);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define move processors and split the available moves between them.
|
* Define move processors and split the available moves between them.
|
||||||
@ -63,7 +69,7 @@ public class AIPlayer extends Player {
|
|||||||
/*
|
/*
|
||||||
* Execute processors, get the best result and pass it back to the Game class
|
* 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);
|
List<ProcessingResult> results = new ArrayList<>(numThreads);
|
||||||
try {
|
try {
|
||||||
List<Future<ProcessingResult>> futures = executor.invokeAll(processors);
|
List<Future<ProcessingResult>> futures = executor.invokeAll(processors);
|
||||||
@ -74,7 +80,18 @@ public class AIPlayer extends Player {
|
|||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
results.sort((r1, r2) -> Integer.compare(r2.score, r1.score));
|
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();
|
}, "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 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.
|
* Create the dialog.
|
||||||
*/
|
*/
|
||||||
public GameModeDialog(BoardPane boardPane) {
|
public GameModeDialog(MainWindow parent, BoardPane boardPane) {
|
||||||
super();
|
super();
|
||||||
setModal(true);
|
setModal(true);
|
||||||
setTitle("Game Mode Selection");
|
setTitle("Game Mode Selection");
|
||||||
@ -46,40 +52,43 @@ public class GameModeDialog extends JDialog {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
final BoardComponent boardComponent = boardPane.getBoardComponent();
|
this.parent = parent;
|
||||||
final OverlayComponent overlayComponent = boardPane.getOverlayComponent();
|
boardComponent = boardPane.getBoardComponent();
|
||||||
final Board board = boardComponent.getBoard();
|
overlayComponent = boardPane.getOverlayComponent();
|
||||||
|
board = boardComponent.getBoard();
|
||||||
|
players = new HashMap<>();
|
||||||
|
|
||||||
JButton btnNatural = new JButton("Game against natural opponent");
|
JButton btnNatural = new JButton("Game against natural opponent");
|
||||||
btnNatural.addActionListener((evt) -> {
|
btnNatural.addActionListener((evt) -> {
|
||||||
Map<Color, Player> players = new HashMap<>();
|
|
||||||
players.put(Color.WHITE, new NaturalPlayer(board, Color.WHITE, overlayComponent));
|
players.put(Color.WHITE, new NaturalPlayer(board, Color.WHITE, overlayComponent));
|
||||||
players.put(Color.BLACK, new NaturalPlayer(board, Color.BLACK, overlayComponent));
|
players.put(Color.BLACK, new NaturalPlayer(board, Color.BLACK, overlayComponent));
|
||||||
new Game(players, boardComponent).start();
|
startGame();
|
||||||
dispose();
|
|
||||||
});
|
});
|
||||||
getContentPane().add(btnNatural);
|
getContentPane().add(btnNatural);
|
||||||
|
|
||||||
JButton btnAI = new JButton("Game against AI");
|
JButton btnAI = new JButton("Game against AI");
|
||||||
btnAI.addActionListener((evt) -> {
|
btnAI.addActionListener((evt) -> {
|
||||||
Map<Color, Player> players = new HashMap<>();
|
|
||||||
players.put(Color.WHITE, new NaturalPlayer(board, Color.WHITE, overlayComponent));
|
players.put(Color.WHITE, new NaturalPlayer(board, Color.WHITE, overlayComponent));
|
||||||
players.put(Color.BLACK, new AIPlayer(board, Color.BLACK, 5));
|
players.put(Color.BLACK, new AIPlayer(board, Color.BLACK, 5));
|
||||||
new Game(players, boardComponent).start();
|
startGame();
|
||||||
dispose();
|
|
||||||
});
|
});
|
||||||
getContentPane().add(btnAI);
|
getContentPane().add(btnAI);
|
||||||
|
|
||||||
JButton btnAI2 = new JButton("AI against AI");
|
JButton btnAI2 = new JButton("AI against AI");
|
||||||
btnAI2.addActionListener((evt) -> {
|
btnAI2.addActionListener((evt) -> {
|
||||||
Map<Color, Player> players = new HashMap<>();
|
|
||||||
players.put(Color.WHITE, new AIPlayer(board, Color.WHITE, 5));
|
players.put(Color.WHITE, new AIPlayer(board, Color.WHITE, 5));
|
||||||
players.put(Color.BLACK, new AIPlayer(board, Color.BLACK, 4));
|
players.put(Color.BLACK, new AIPlayer(board, Color.BLACK, 4));
|
||||||
new Game(players, boardComponent).start();
|
startGame();
|
||||||
dispose();
|
|
||||||
});
|
});
|
||||||
getContentPane().add(btnAI2);
|
getContentPane().add(btnAI2);
|
||||||
|
|
||||||
setLocationRelativeTo(null);
|
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 javax.swing.JPanel;
|
||||||
|
|
||||||
import dev.kske.chess.board.Board;
|
import dev.kske.chess.board.Board;
|
||||||
|
import dev.kske.chess.game.Game;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Project: <strong>Chess</strong><br>
|
* Project: <strong>Chess</strong><br>
|
||||||
@ -18,7 +18,8 @@ import dev.kske.chess.board.Board;
|
|||||||
*/
|
*/
|
||||||
public class MainWindow {
|
public class MainWindow {
|
||||||
|
|
||||||
private JFrame mframe;
|
private JFrame mframe;
|
||||||
|
private Game game;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Launch the application.
|
* Launch the application.
|
||||||
@ -61,12 +62,16 @@ public class MainWindow {
|
|||||||
mframe.getContentPane().add(toolPanel, BorderLayout.NORTH);
|
mframe.getContentPane().add(toolPanel, BorderLayout.NORTH);
|
||||||
|
|
||||||
JButton btnRestart = new JButton("Restart");
|
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);
|
toolPanel.add(btnRestart);
|
||||||
mframe.pack();
|
mframe.pack();
|
||||||
mframe.setLocationRelativeTo(null);
|
mframe.setLocationRelativeTo(null);
|
||||||
|
|
||||||
// Display dialog for game mode selection
|
// 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