diff --git a/src/controller/Game.java b/src/controller/Game.java index 2ca5991..5018c5d 100755 --- a/src/controller/Game.java +++ b/src/controller/Game.java @@ -1,11 +1,28 @@ package controller; +import java.util.ArrayList; + import model.Board; import model.Color; +import model.Location; +import model.Move; public class Game { private Board board; private Color current_turn; + + public void movePiece(Move move) { + board.move(move); + } + + public ArrayList getAvailableMoves(Location source) { + ArrayList moves = board.generateMoves(board.getPiece(source)); + ArrayList jumps = board.generateJumpMoves(board.getPiece(source)); + + ArrayList allMoves = new ArrayList(moves); + allMoves.addAll(jumps); + return allMoves; + } public Game(Color start) { this.board = new Board(); diff --git a/src/model/Board.java b/src/model/Board.java index 6d672da..1104728 100755 --- a/src/model/Board.java +++ b/src/model/Board.java @@ -53,8 +53,8 @@ public boolean isValidSquare(Location location) { private void init() { for (int row = 0; row < 3; row++){ for (int col = 0; col < 4; col++) { - Piece red_piece = new Piece(Color.RED, 2*col + (row % 2), row); - Piece black_piece = new Piece(Color.BLACK, 2*col + (BOARD_SIZE - 1 - row) %2, BOARD_SIZE - 1 - row); + Piece red_piece = new Piece(Color.RED, row, 2*col + (row % 2)); + Piece black_piece = new Piece(Color.BLACK, BOARD_SIZE - 1 - row, 2*col + (BOARD_SIZE - 1 - row) %2); representation[row][2*col+ (row % 2)] = red_piece; representation[BOARD_SIZE - 1 - row][2*col + (BOARD_SIZE - 1 - row) %2] = black_piece; } @@ -261,13 +261,18 @@ else if (representation[row][col].getColor() == Color.RED) { * @return */ public boolean isValidJump(Move move) { - Piece monkey = representation[(move.destination.row + move.source.row)/2][(move.destination.column + move.source.column)/2]; - Piece toMove = representation[move.source.row][move.source.column]; - return isValidSquare(move.destination) && !isOccupied(move.destination) - && monkey != null - && monkey.getColor() == toMove.opposite(); + if (isValidSquare(move.destination)) { + Piece monkey = representation[(move.destination.row + move.source.row)/2][(move.destination.column + move.source.column)/2]; + Piece toMove = representation[move.source.row][move.source.column]; + return !isOccupied(move.destination) + && monkey != null + && monkey.getColor() == toMove.opposite(); + + } else { + return false; + } } - + public boolean isValidMove(Move move) { return isValidSquare(move.destination) && !isOccupied(move.destination); } @@ -279,6 +284,10 @@ public boolean isValidMove(Move move) { public boolean isOccupied(Location location) { return representation[location.row][location.column] != null; } + + public Piece getPiece(Location location) { + return representation[location.row][location.column]; + } public Piece[][] getRepresentation() { diff --git a/src/test/GUITest.java b/src/test/GUITest.java index 0cacc2d..7127027 100644 --- a/src/test/GUITest.java +++ b/src/test/GUITest.java @@ -3,6 +3,8 @@ import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; +import controller.Game; +import model.Color; import view.CheckersWindow; public class GUITest { @@ -27,7 +29,7 @@ public static void main(String[] args) { catch (IllegalAccessException e) { // handle exception } - CheckersWindow window = new CheckersWindow(); + CheckersWindow window = new CheckersWindow(new Game(Color.RED)); window.open(); } } diff --git a/src/view/CheckersCanvas.java b/src/view/CheckersCanvas.java index 5142c93..252f9fe 100644 --- a/src/view/CheckersCanvas.java +++ b/src/view/CheckersCanvas.java @@ -28,14 +28,14 @@ public class CheckersCanvas extends JPanel { public CheckersCanvas(GameEventListener boardListener) { super(new GridLayout(BOARD_DIM, BOARD_DIM)); this.board = new Square[BOARD_DIM][BOARD_DIM]; - + this.setPreferredSize(new Dimension(CANVAS_SIZE, CANVAS_SIZE)); this.setMaximumSize(new Dimension(CANVAS_SIZE, CANVAS_SIZE)); this.setMinimumSize(new Dimension(CANVAS_SIZE, CANVAS_SIZE)); - + this.initCanvas(boardListener); } - + private void initCanvas(GameEventListener boardListener) { initSquares(boardListener); initCheckers(); @@ -64,7 +64,7 @@ private void initSquares(GameEventListener boardListener) { board[i][j*2] = redSquare; redSquare.addMouseListener(boardListener); this.add(redSquare); - + /* Create a black square */ Square blackSquare = new Square(Color.BLACK, new Location(i, j*2 + 1)); board[i][j*2 + 1] = blackSquare; @@ -74,16 +74,41 @@ private void initSquares(GameEventListener boardListener) { } } } - + private void initCheckers() { for (int row = 0; row < BOARD_DIM / 2 - 1; ++row) { for (int col = 0; col < BOARD_DIM / 2; ++col) { Checker redChecker = new Checker(new Color(255, 51, 51)); Checker blackChecker = new Checker(new Color(89, 89, 89)); board[row][2*col+ (row % 2)].setPiece(redChecker); - board[BOARD_DIM - 1 - row][2*col + (BOARD_DIM - 1 - row) %2].setPiece(blackChecker); + board[BOARD_DIM - 1 - row][2*col + (BOARD_DIM - 1 - row) %2] + .setPiece(blackChecker); } } } + public void highlightAndValidateSquare(Location location) { + board[location.row][location.column].highlight(); + board[location.row][location.column].setValid(true); + } + + public void dehighlightAndInvalidateSquare(Location location) { + board[location.row][location.column].dehighlight(); + board[location.row][location.column].setValid(false); + } + + public void invalidateAllSquares() { + for (int row = 0; row < BOARD_DIM; ++row) { + for (int col = 0; col < BOARD_DIM; ++col) { + dehighlightAndInvalidateSquare(new Location(row, col)); + } + } + } + + public void moveChecker(Location source, Location destination) { + board[destination.row][destination.column].setPiece(board[source.row] + [source.column].getPiece()); + board[source.row][source.column].setPiece(null); + + } } diff --git a/src/view/CheckersWindow.java b/src/view/CheckersWindow.java index d554b61..9a89393 100644 --- a/src/view/CheckersWindow.java +++ b/src/view/CheckersWindow.java @@ -7,6 +7,8 @@ import javax.swing.JMenuBar; import javax.swing.JMenuItem; +import controller.Game; + /** * Represents the JFrame window that will hold the graphical components * of the game. @@ -32,7 +34,7 @@ public class CheckersWindow extends JFrame { private GameEventListener gameListener; - public CheckersWindow() { + public CheckersWindow(Game game) { super("Checkers"); this.setSize(WIDTH, HEIGHT); this.setDefaultCloseOperation(EXIT_ON_CLOSE); @@ -42,7 +44,7 @@ public CheckersWindow() { /* MUST be done in this order */ this.initGameListener(); this.createMenuBar(); - this.initGamePanel(); + this.initGamePanel(game); this.pack(); } @@ -96,8 +98,8 @@ private void createMenuBar() { /** * Initializes the {@link GamePanel} instance */ - private void initGamePanel() { - this.gamePanel = new GamePanel(gameListener); + private void initGamePanel(Game game) { + this.gamePanel = new GamePanel(game, gameListener); this.getContentPane().add(this.gamePanel); this.gameListener.setGamePanel(gamePanel); } diff --git a/src/view/GameEventListener.java b/src/view/GameEventListener.java index a6f3488..7d6cbec 100644 --- a/src/view/GameEventListener.java +++ b/src/view/GameEventListener.java @@ -34,9 +34,12 @@ public void mouseExited(MouseEvent e) {} public void mousePressed(MouseEvent e) { Square square = (Square) e.getComponent(); if(square.hasPiece()) { + gamePanel.dehighlightAllSquares(); gamePanel.setMoveSource(square); + if (square.isSelected()) + gamePanel.highlightValidDestinations(square.getCellLocation()); gamePanel.updateMoveMessage(); - } else { + } else if (square.isValid()) { gamePanel.setMoveDestination(square); gamePanel.updateMoveMessage(); } @@ -52,8 +55,7 @@ public void keyPressed(KeyEvent arg0) {} @Override public void keyReleased(KeyEvent e) { if(e.getKeyCode() == KeyEvent.VK_ENTER && gamePanel.moveReady()) { - System.out.println("Moving piece."); - // TODO: Request a move from the controller. + gamePanel.moveSelectedPiece(); } } diff --git a/src/view/GamePanel.java b/src/view/GamePanel.java index bb1b88e..7068706 100644 --- a/src/view/GamePanel.java +++ b/src/view/GamePanel.java @@ -2,10 +2,15 @@ import java.awt.GridBagConstraints; import java.awt.GridBagLayout; +import java.util.ArrayList; import javax.swing.JLabel; import javax.swing.JPanel; +import controller.Game; +import model.Location; +import model.Move; + /** * Represents the panel which will hold all of the graphical * components of the game. @@ -14,6 +19,9 @@ */ @SuppressWarnings("serial") public class GamePanel extends JPanel { + + private Game game; + private JLabel messageBar; private CheckersCanvas canvas; private GridBagConstraints layoutConstraints; @@ -21,9 +29,11 @@ public class GamePanel extends JPanel { private Square moveDestination; private Square moveSource; - public GamePanel(GameEventListener gameListener) { + public GamePanel(Game game, GameEventListener gameListener) { super(new GridBagLayout()); + this.game = game; + /* Initialize the layout manager */ this.layoutConstraints = new GridBagConstraints(); this.layoutConstraints.gridy = 0; @@ -94,4 +104,26 @@ public boolean moveReady() { return moveSource != null && moveDestination != null; } + public void highlightValidDestinations(Location source) { + ArrayList availMoves = game.getAvailableMoves(source); + + for (Move move : availMoves) { + canvas.highlightAndValidateSquare(move.destination); + } + } + + public void dehighlightAllSquares() { + canvas.invalidateAllSquares(); + } + + public void moveSelectedPiece() { + game.movePiece(new Move(moveSource.getCellLocation(), moveDestination.getCellLocation())); + canvas.moveChecker(moveSource.getCellLocation(), moveDestination.getCellLocation()); + dehighlightAllSquares(); + moveSource.setSelected(false); + moveDestination.setSelected(false); + moveSource = null; + moveDestination = null; + } + } diff --git a/src/view/Square.java b/src/view/Square.java index 75d7bfc..b51112b 100644 --- a/src/view/Square.java +++ b/src/view/Square.java @@ -18,18 +18,20 @@ public class Square extends JPanel implements MouseListener { * The {@link Location} (row, col) of the square on the board. */ private final Location location; - + /** * The {@link Checker} object contained in this square. Null if there is none. */ private Checker piece; - + /** * A boolean value representing whether the square is selected for movement. */ private boolean selected; - - + + private boolean valid; + + /** * Constructs a graphical square with the given color and location. * @param color A {@link Color} object representing the square's color. @@ -41,7 +43,7 @@ public Square(Color color, Location location) { this.selected = false; initSquare(color); } - + /** * Initializes the properties of the square such as color and layout. @@ -73,11 +75,13 @@ public Checker getPiece() { */ public void setPiece(Checker piece) { this.piece = piece; - this.add(piece); - piece.addMouseListener(this); - this.validate(); + if (piece != null) { + this.add(piece); + piece.addMouseListener(this); + this.validate(); + } } - + /** * {@link Square#selected} */ @@ -92,13 +96,23 @@ public boolean isSelected() { */ public void setSelected(boolean val) { if (val) { - this.setBorder(BorderFactory.createLineBorder(Color.WHITE)); + this.setBorder(BorderFactory.createLineBorder(Color.GREEN)); + } else if (valid){ + this.setBorder(BorderFactory.createLineBorder(Color.YELLOW)); } else { this.setBorder(null); } this.selected = val; } - + + public void setValid(boolean state) { + this.valid = state; + } + + public boolean isValid() { + return valid; + } + /** * Check's if the square contains a {@link Checker} object or not. * @return true if the square contains a checker.
@@ -107,7 +121,7 @@ public void setSelected(boolean val) { public boolean hasPiece() { return this.piece != null; } - + @Override public void mousePressed(MouseEvent e) { /* Send the event to the lister of the square (GameEventListener) */ @@ -129,4 +143,16 @@ public void mouseExited(MouseEvent arg0) {} public void mouseReleased(MouseEvent arg0) {} + public void highlight() { + this.setBorder(BorderFactory.createLineBorder(Color.YELLOW)); + + } + + + public void dehighlight() { + this.setBorder(null); + + } + + }