diff --git a/src/dev/kske/chess/game/Game.java b/src/dev/kske/chess/game/Game.java new file mode 100644 index 0000000..80fad76 --- /dev/null +++ b/src/dev/kske/chess/game/Game.java @@ -0,0 +1,41 @@ +package dev.kske.chess.game; + +import java.util.Map; + +import dev.kske.chess.board.Board; +import dev.kske.chess.board.Move; +import dev.kske.chess.board.Piece.Color; + +/** + * Project: Chess
+ * File: Game.java
+ * Created: 06.07.2019
+ * Author: Kai S. K. Engelbart + */ +public class Game { + + private Map players; + private Board board; + + public Game(Map players, Board board) { + this.players = players; + this.board = board; + + // Initialize the game variable in each player + 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); + players.get(player.color.opposite()).requestMove(); + } else { + System.out.printf("%s: Illegal move!%n", player.getColor()); + player.requestMove(); + } + } +} diff --git a/src/dev/kske/chess/game/NaturalPlayer.java b/src/dev/kske/chess/game/NaturalPlayer.java new file mode 100644 index 0000000..b30225d --- /dev/null +++ b/src/dev/kske/chess/game/NaturalPlayer.java @@ -0,0 +1,56 @@ +package dev.kske.chess.game; + +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +import dev.kske.chess.board.Board; +import dev.kske.chess.board.Move; +import dev.kske.chess.board.Piece.Color; +import dev.kske.chess.board.Position; +import dev.kske.chess.ui.BoardPanel; + +/** + * Project: Chess
+ * File: NaturalPlayer.java
+ * Created: 06.07.2019
+ * Author: Kai S. K. Engelbart + */ +public class NaturalPlayer extends Player { + + private boolean moveRequested; + + public NaturalPlayer(Board board, Color color, BoardPanel boardPanel) { + super(board, color); + moveRequested = false; + boardPanel.addMouseListener(new MouseAdapter() { + + private Position pos; + + @Override + public void mousePressed(MouseEvent evt) { + if (!moveRequested) return; + if (pos == null) { + pos = new Position(evt.getPoint().x / boardPanel.getTileSize(), + evt.getPoint().y / boardPanel.getTileSize()); + + if (board.get(pos) != null && board.get(pos).getColor() == color) + boardPanel.displayMoves(board.getMoves(pos)); + else pos = null; + } else { + Position dest = new Position(evt.getPoint().x / boardPanel.getTileSize(), + evt.getPoint().y / boardPanel.getTileSize()); + + boardPanel.clearDisplayMoves(); + moveRequested = false; + game.onMove(NaturalPlayer.this, new Move(pos, dest)); + pos = null; + } + } + }); + } + + @Override + public void requestMove() { + moveRequested = true; + } +} diff --git a/src/dev/kske/chess/game/Player.java b/src/dev/kske/chess/game/Player.java new file mode 100644 index 0000000..fd34dde --- /dev/null +++ b/src/dev/kske/chess/game/Player.java @@ -0,0 +1,36 @@ +package dev.kske.chess.game; + +import dev.kske.chess.board.Board; +import dev.kske.chess.board.Piece.Color; + +/** + * Project: Chess
+ * File: Player.java
+ * Created: 06.07.2019
+ * Author: Kai S. K. Engelbart + */ +public abstract class Player { + + protected Game game; + protected Board board; + protected Color color; + + public Player(Board board, Color color) { + this.board = board; + this.color = color; + } + + public abstract void requestMove(); + + public Game getGame() { return game; } + + public void setGame(Game game) { this.game = game; } + + public Board getBoard() { return board; } + + public void setBoard(Board board) { this.board = board; } + + public Color getColor() { return color; } + + public void setColor(Color color) { this.color = color; } +} diff --git a/src/dev/kske/chess/ui/BoardPanel.java b/src/dev/kske/chess/ui/BoardPanel.java index d5e4269..a068ce5 100644 --- a/src/dev/kske/chess/ui/BoardPanel.java +++ b/src/dev/kske/chess/ui/BoardPanel.java @@ -5,8 +5,6 @@ import java.awt.Dimension; import java.awt.Graphics; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.List; @@ -15,7 +13,6 @@ import javax.swing.JPanel; import dev.kske.chess.board.Board; import dev.kske.chess.board.Move; -import dev.kske.chess.board.Position; import dev.kske.chess.event.GameEvent; import dev.kske.chess.event.GameEventListener; @@ -61,33 +58,6 @@ public class BoardPanel extends JPanel implements GameEventListener { }); setSize(getPreferredSize()); - - // Add a mouse adapter for testing piece movement - addMouseListener(new MouseAdapter() { - - private Position pos; - - @Override - public void mousePressed(MouseEvent evt) { - if (pos == null) { - pos = new Position(evt.getPoint().x / tileSize, evt.getPoint().y / tileSize); - - if (board.get(pos) != null) { - displayMoves.clear(); - displayMoves.addAll(board.getMoves(pos)); - repaint(); - } - } else { - Position dest = new Position(evt.getPoint().x / tileSize, evt.getPoint().y / tileSize); - - if (board.attemptMove(new Move(pos, dest))) { - displayMoves.clear(); - repaint(); - } - pos = null; - } - } - }); } @Override @@ -133,7 +103,26 @@ public class BoardPanel extends JPanel implements GameEventListener { } /** - * Reverts the board to its initial state + * Displays move destinations on the board. + * + * @param moves The moves to display + */ + public void displayMoves(List moves) { + displayMoves.clear(); + displayMoves.addAll(moves); + repaint(); + } + + /** + * Clears all display moves. + */ + public void clearDisplayMoves() { + displayMoves.clear(); + repaint(); + } + + /** + * Reverts the board to its initial state. */ public void reset() { board.initializeDefaultPositions(); @@ -149,6 +138,8 @@ public class BoardPanel extends JPanel implements GameEventListener { @Override public Dimension getPreferredSize() { return new Dimension(480, 480); } + public int getTileSize() { return tileSize; } + public Board getBoard() { return board; } public void setBoard(Board board) { diff --git a/src/dev/kske/chess/ui/GameModeDialog.java b/src/dev/kske/chess/ui/GameModeDialog.java new file mode 100644 index 0000000..5461767 --- /dev/null +++ b/src/dev/kske/chess/ui/GameModeDialog.java @@ -0,0 +1,49 @@ +package dev.kske.chess.ui; + +import java.awt.FlowLayout; +import java.util.HashMap; +import java.util.Map; + +import javax.swing.JButton; +import javax.swing.JDialog; + +import dev.kske.chess.board.Piece.Color; +import dev.kske.chess.game.Game; +import dev.kske.chess.game.NaturalPlayer; +import dev.kske.chess.game.Player; + +/** + * Project: Chess
+ * File: GameModeDialog.java
+ * Created: 06.07.2019
+ * Author: Kai S. K. Engelbart + */ +public class GameModeDialog extends JDialog { + + private static final long serialVersionUID = 5470026233924735607L; + + /** + * Create the dialog. + */ + public GameModeDialog(BoardPanel boardPanel) { + super(); + setModal(true); + setTitle("Game Mode Selection"); + setBounds(100, 100, 231, 99); + setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); + getContentPane().setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5)); + + JButton btnNatural = new JButton("Game against natural opponent"); + btnNatural.addActionListener((evt) -> { + Map players = new HashMap<>(); + players.put(Color.WHITE, new NaturalPlayer(boardPanel.getBoard(), Color.WHITE, boardPanel)); + players.put(Color.BLACK, new NaturalPlayer(boardPanel.getBoard(), Color.BLACK, boardPanel)); + new Game(players, boardPanel.getBoard()).start(); + dispose(); + }); + getContentPane().add(btnNatural); + + JButton btnAI = new JButton("Game against AI"); + getContentPane().add(btnAI); + } +} diff --git a/src/dev/kske/chess/ui/MainWindow.java b/src/dev/kske/chess/ui/MainWindow.java index 33c7574..8784f42 100644 --- a/src/dev/kske/chess/ui/MainWindow.java +++ b/src/dev/kske/chess/ui/MainWindow.java @@ -64,5 +64,8 @@ public class MainWindow { btnRestart.addActionListener((evt) -> boardPanel.reset()); toolPanel.add(btnRestart); mframe.pack(); + + // Display dialog for game mode selection + new GameModeDialog(boardPanel).setVisible(true); } }