package org.fhnw.aigs.Minesweeper.client; import javafx.event.EventHandler; import javafx.scene.input.MouseButton; import javafx.scene.input.MouseEvent; import org.fhnw.aigs.client.GUI.BaseBoard; import org.fhnw.aigs.client.gameHandling.ClientGame; import org.fhnw.aigs.Minesweeper.commons.BoardChangeMessage; import org.fhnw.aigs.Minesweeper.commons.MarkFieldMessage; import org.fhnw.aigs.Minesweeper.commons.MarkFieldStatusMesage; import org.fhnw.aigs.Minesweeper.commons.MinesweeperField; import org.fhnw.aigs.commons.communication.FieldClickMessage; import org.fhnw.aigs.commons.communication.Message; /** * This is the class representing the Minesweeper board. * It contains x x y MinesweeperPanes. * All event handlers and animations as well as the creation of the MinesweeperPanes * occurs here.<br> * v1.0 Initial release<br> * v1.1 Change of handling and UI improvements * * @author Matthias Stöckli (v1.0) * @version v1.1 (Raphael Stoeckli, 04.11.2014) */ public class MinesweeperBoard extends BaseBoard { /** * Create a new instance of MinesweeperBoard. * @param fieldsX Number of fields in the x-axis. * @param fieldsY Number of fields in the y-axis. * @param clientGame Reference to the ClientGame. */ public MinesweeperBoard(int fieldsX, int fieldsY, ClientGame clientGame) { super(fieldsX, fieldsY, clientGame); this.setFields(); this.setEventHandlers(); } /** * Sets up the Minesweeper fields (graphical representations). */ @Override public void setFields() { for (int i = 0; i < fieldsX; i++) { for (int j = 0; j < fieldsY; j++) { MinesweeperPane pane = new MinesweeperPane(); fieldPanes[i][j] = pane; this.add(pane, i, j); } } } /** * Changes the GUI according to the incoming messages. * @param message The incoming message. */ @Override public void manipulateGUI(Message message) { // Flags or unflags a field. if (message instanceof MarkFieldStatusMesage) { handleMarkFieldStatusMessage((MarkFieldStatusMesage)message); } // Covers or uncovers a field. else if (message instanceof BoardChangeMessage) { handleBoardChangeMessage((BoardChangeMessage) message); } } /** * Wires the following actions to the fields: When a player clicks the * primary button (left mouse button), the field will be uncovered. If he or * she clicks the secondary button (right mouse button), then the field will * be flagged. */ @Override public void setEventHandlers() { // Go through all fields for (int i = 0; i < this.getFieldsX(); i++) { for (int j = 0; j < this.getFieldsY(); j++) { // Set an anonymous event handler which reacts on clicks this.getField(i, j).setOnMouseClicked( new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent event) { MinesweeperPane sourceField = (MinesweeperPane) event.getSource(); // Get the source, i.e. which field was clicked int xPosition = getColumnIndex(sourceField); // Get the column int yPosition = getRowIndex(sourceField); // Get the row if (event.getButton().equals(MouseButton.PRIMARY)) { // Handle left click // Create a field click message based on the coordinates FieldClickMessage fieldClickMessage = new FieldClickMessage(xPosition, yPosition); clientGame.sendMessageToServer(fieldClickMessage); } else if (event.getButton().equals(MouseButton.SECONDARY)) { // Handle right click (mark mine) MarkFieldMessage markFieldMessage = new MarkFieldMessage(xPosition, yPosition); clientGame.sendMessageToServer(markFieldMessage); } } }); } } } /** * Covers all fields and removes all images. */ public void restartBoard() { for (int i = 0; i < fieldsX; i++) { for (int j = 0; j < fieldsY; j++) { ((MinesweeperPane) fieldPanes[i][j]).removeImage(); ((MinesweeperPane) fieldPanes[i][j]).cover(); } } } /** * Unflags or flags the field. * @param markFieldStatusMesage The MarkFieldStatusMessage */ private void handleMarkFieldStatusMessage(MarkFieldStatusMesage markFieldStatusMesage) { int x = markFieldStatusMesage.getPositionX(); int y = markFieldStatusMesage.getPositionY(); if (markFieldStatusMesage.getHasFlag()) { ((MinesweeperPane) fieldPanes[x][y]).setFlag(); } else { ((MinesweeperPane) fieldPanes[x][y]).removeImage(); } } /** * Covers or uncovers an array of fields. * @param boardChangeMessage The BoardChangeMessage. */ private void handleBoardChangeMessage(BoardChangeMessage boardChangeMessage) { for (MinesweeperField field : boardChangeMessage.getUncoveredMinesweeperFields()) { int x = field.getxPosition(); int y = field.getyPosition(); if (field.getHasFlag()) { ((MinesweeperClientGame) clientGame).increaseMinesLeft(); } ((MinesweeperPane) fieldPanes[x][y]).uncover(field); } } }