From 30074f385ef3560a01184e826c29badc16ad7064 Mon Sep 17 00:00:00 2001 From: kske Date: Wed, 3 Jul 2019 11:05:20 +0200 Subject: [PATCH] Added tool panel and event system for check notification + GameEvent and GameEventListener + Check detection and notification in Board and BoardPanel + Tool panel in Chess with a restart button --- src/dev/kske/chess/Board.java | 30 ++++++++++++++- src/dev/kske/chess/BoardPanel.java | 34 ++++++++++++++--- src/dev/kske/chess/Chess.java | 12 +++++- src/dev/kske/chess/event/GameEvent.java | 38 +++++++++++++++++++ .../kske/chess/event/GameEventListener.java | 12 ++++++ 5 files changed, 117 insertions(+), 9 deletions(-) create mode 100644 src/dev/kske/chess/event/GameEvent.java create mode 100644 src/dev/kske/chess/event/GameEventListener.java diff --git a/src/dev/kske/chess/Board.java b/src/dev/kske/chess/Board.java index dbe9825..952407c 100644 --- a/src/dev/kske/chess/Board.java +++ b/src/dev/kske/chess/Board.java @@ -1,8 +1,13 @@ package dev.kske.chess; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; +import dev.kske.chess.event.GameEvent; +import dev.kske.chess.event.GameEvent.GameEventType; +import dev.kske.chess.event.GameEventListener; import dev.kske.chess.piece.Bishop; import dev.kske.chess.piece.King; import dev.kske.chess.piece.Knight; @@ -24,9 +29,12 @@ public class Board { private Piece[][] boardArr; private Map kingPos; + private List gameEventListeners; + public Board() { boardArr = new Piece[8][8]; kingPos = new HashMap<>(); + gameEventListeners = new ArrayList<>(); initializeDefaultPositions(); } @@ -52,6 +60,13 @@ public class Board { revert(move, capturePiece); return false; } + + // TODO: detecting checkmate + // Check for check on the opposite team + Color oppositeColor = piece.getColor() == Color.WHITE ? Color.BLACK : Color.WHITE; + if (checkCheck(oppositeColor)) + notifyListeners(new GameEvent(this, GameEventType.CHECK, oppositeColor)); + return true; } } @@ -80,6 +95,14 @@ public class Board { return false; } + public void registerGameEventListener(GameEventListener listener) { + gameEventListeners.add(listener); + } + + private void notifyListeners(GameEvent evt) { + gameEventListeners.forEach(listener -> listener.onGameEvent(evt)); + } + public Piece get(Position pos) { return boardArr[pos.x][pos.y]; } @@ -107,7 +130,7 @@ public class Board { /** * Initialized the board array with the default chess pieces and positions. */ - private void initializeDefaultPositions() { + public void initializeDefaultPositions() { // Initialize pawns for (int i = 0; i < 8; i++) { boardArr[i][1] = new Pawn(Color.BLACK, this); @@ -143,6 +166,11 @@ public class Board { boardArr[2][7] = new Bishop(Color.WHITE, this); boardArr[5][0] = new Bishop(Color.BLACK, this); boardArr[5][7] = new Bishop(Color.WHITE, this); + + // Clear all other tiles + for (int i = 0; i < 8; i++) + for (int j = 2; j < 6; j++) + boardArr[i][j] = null; } /** diff --git a/src/dev/kske/chess/BoardPanel.java b/src/dev/kske/chess/BoardPanel.java index dbe5491..9ccbba0 100644 --- a/src/dev/kske/chess/BoardPanel.java +++ b/src/dev/kske/chess/BoardPanel.java @@ -13,8 +13,11 @@ import java.io.File; import java.util.HashMap; import java.util.Map; +import javax.swing.JOptionPane; import javax.swing.JPanel; +import dev.kske.chess.event.GameEvent; +import dev.kske.chess.event.GameEventListener; import dev.kske.chess.piece.Piece; /** @@ -27,7 +30,7 @@ import dev.kske.chess.piece.Piece; * this must be added to a parent component that allows the child to decide the * size. */ -public class BoardPanel extends JPanel { +public class BoardPanel extends JPanel implements GameEventListener { private static final long serialVersionUID = 6771148331334310216L; @@ -37,14 +40,11 @@ public class BoardPanel extends JPanel { private Board board; - static { - loadPieceTextures(); - } - public BoardPanel(Board board) { this(); setSize(getPreferredSize()); setBoard(board); + if (textures == null) loadPieceTextures(); } public BoardPanel() { @@ -99,6 +99,23 @@ public class BoardPanel extends JPanel { g.drawImage(getPieceTexture(board.getBoardArr()[i][j]), i * tileSize, j * tileSize, this); } + @Override + public void onGameEvent(GameEvent evt) { + switch (evt.getEventType()) { + case CHECK: + JOptionPane.showMessageDialog(this, evt.getColor().toString() + " in check!"); + break; + } + } + + /** + * Reverts the board to its initial state + */ + public void reset() { + board.initializeDefaultPositions(); + repaint(); + } + /** * Load every PNG file inside the res/pieces directory. * The filenames without extensions are used as keys in the map textures. @@ -140,5 +157,10 @@ public class BoardPanel extends JPanel { public Board getBoard() { return board; } - public void setBoard(Board board) { this.board = board; } + public void setBoard(Board board) { + this.board = board; + + // Register this BoardPanel as a GameEventListener to the board + board.registerGameEventListener(this); + } } diff --git a/src/dev/kske/chess/Chess.java b/src/dev/kske/chess/Chess.java index fe30759..58be468 100644 --- a/src/dev/kske/chess/Chess.java +++ b/src/dev/kske/chess/Chess.java @@ -3,7 +3,9 @@ package dev.kske.chess; import java.awt.BorderLayout; import java.awt.EventQueue; +import javax.swing.JButton; import javax.swing.JFrame; +import javax.swing.JPanel; /** @@ -46,13 +48,19 @@ public class Chess { private void initialize() { mframe = new JFrame(); mframe.setResizable(false); - mframe.setBounds(100, 100, 729, 737); + mframe.setBounds(100, 100, 494, 565); mframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); BoardPanel boardPanel = new BoardPanel(new Board()); boardPanel.setLayout(null); mframe.getContentPane().add(boardPanel, BorderLayout.CENTER); + + JPanel toolPanel = new JPanel(); + mframe.getContentPane().add(toolPanel, BorderLayout.NORTH); + + JButton btnRestart = new JButton("Restart"); + btnRestart.addActionListener((evt) -> boardPanel.reset()); + toolPanel.add(btnRestart); mframe.pack(); } - } diff --git a/src/dev/kske/chess/event/GameEvent.java b/src/dev/kske/chess/event/GameEvent.java new file mode 100644 index 0000000..21eb20d --- /dev/null +++ b/src/dev/kske/chess/event/GameEvent.java @@ -0,0 +1,38 @@ +package dev.kske.chess.event; + +import java.util.EventObject; + +import dev.kske.chess.Board; +import dev.kske.chess.piece.Piece.Color; + +/** + * Project: Chess
+ * File: GameEvent.java
+ * Created: 03.07.2019
+ * Author: Kai S. K. Engelbart + */ +public class GameEvent extends EventObject { + + private static final long serialVersionUID = -6783035746521826589L; + + private final Board source; + private final GameEventType eventType; + private final Color color; + + public GameEvent(Board source, GameEventType eventType, Color color) { + super(source); + this.source = source; + this.eventType = eventType; + this.color = color; + } + + public Board getSource() { return source; } + + public GameEventType getEventType() { return eventType; } + + public Color getColor() { return color; } + + public static enum GameEventType { + CHECK, CHECKMATE + } +} diff --git a/src/dev/kske/chess/event/GameEventListener.java b/src/dev/kske/chess/event/GameEventListener.java new file mode 100644 index 0000000..f01ee6a --- /dev/null +++ b/src/dev/kske/chess/event/GameEventListener.java @@ -0,0 +1,12 @@ +package dev.kske.chess.event; + +/** + * Project: Chess
+ * File: GameEventListener.java
+ * Created: 03.07.2019
+ * Author: Kai S. K. Engelbart + */ +public interface GameEventListener { + + void onGameEvent(GameEvent evt); +}