diff --git a/src/main/java/edu/rpi/legup/puzzle/minesweeper/MinesweeperBoard.java b/src/main/java/edu/rpi/legup/puzzle/minesweeper/MinesweeperBoard.java index 696d42113..ea6f560e1 100644 --- a/src/main/java/edu/rpi/legup/puzzle/minesweeper/MinesweeperBoard.java +++ b/src/main/java/edu/rpi/legup/puzzle/minesweeper/MinesweeperBoard.java @@ -16,4 +16,21 @@ public MinesweeperBoard(int size) { public MinesweeperCell getCell(int x, int y) { return (MinesweeperCell) super.getCell(x, y); } + + + /** + * Performs a deep copy of the Board + * + * @return a new copy of the board that is independent of this one + */ + @Override + public MinesweeperBoard copy() { + MinesweeperBoard newMinesweeperBoard = new MinesweeperBoard(this.dimension.width, this.dimension.height); + for (int x = 0; x < this.dimension.width; x++) { + for (int y = 0; y < this.dimension.height; y++) { + newMinesweeperBoard.setCell(x, y, getCell(x, y).copy()); + } + } + return newMinesweeperBoard; + } } diff --git a/src/main/java/edu/rpi/legup/puzzle/minesweeper/MinesweeperElementView.java b/src/main/java/edu/rpi/legup/puzzle/minesweeper/MinesweeperElementView.java index 6384b3d99..e9658a077 100644 --- a/src/main/java/edu/rpi/legup/puzzle/minesweeper/MinesweeperElementView.java +++ b/src/main/java/edu/rpi/legup/puzzle/minesweeper/MinesweeperElementView.java @@ -1,5 +1,6 @@ package edu.rpi.legup.puzzle.minesweeper; +import edu.rpi.legup.puzzle.lightup.LightUpView; import edu.rpi.legup.ui.boardview.GridElementView; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; @@ -58,5 +59,19 @@ public void drawElement(@NotNull Graphics2D graphics2D) { graphics2D.setColor(Color.GRAY); graphics2D.fillRect(location.x, location.y, size.width, size.height); } + if (type == MinesweeperTileType.BOMB) { + graphics2D.setColor(Color.LIGHT_GRAY); + graphics2D.fillRect(location.x, location.y, size.width, size.height); + graphics2D.drawImage( + MinesweeperView.BOMB_IMAGE, + location.x, + location.y, + size.width, + size.height, + Color.GRAY, + null); + graphics2D.setColor(Color.BLACK); + graphics2D.drawRect(location.x, location.y, size.width, size.height); + } } } diff --git a/src/main/java/edu/rpi/legup/puzzle/minesweeper/MinesweeperView.java b/src/main/java/edu/rpi/legup/puzzle/minesweeper/MinesweeperView.java index 78747a199..ca9214416 100644 --- a/src/main/java/edu/rpi/legup/puzzle/minesweeper/MinesweeperView.java +++ b/src/main/java/edu/rpi/legup/puzzle/minesweeper/MinesweeperView.java @@ -2,13 +2,36 @@ import edu.rpi.legup.controller.BoardController; import edu.rpi.legup.model.gameboard.PuzzleElement; +import edu.rpi.legup.puzzle.lightup.LightUpView; import edu.rpi.legup.ui.boardview.GridBoardView; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.NotNull; +import javax.imageio.ImageIO; import java.awt.*; +import java.io.IOException; +import java.util.Objects; public class MinesweeperView extends GridBoardView { + private static final Logger LOGGER = LogManager.getLogger(MinesweeperView.class.getName()); + public static final Image BOMB_IMAGE; + + static { + Image tempBombImage = null; + try { + tempBombImage = + ImageIO.read( + Objects.requireNonNull(ClassLoader.getSystemClassLoader() + .getResource("edu/rpi/legup/images/minesweeper/tiles/Bomb.png"))); + } catch (IOException e) { + LOGGER.error("Failed to open Minesweeper images"); + } + BOMB_IMAGE = tempBombImage; + } + + public MinesweeperView(@NotNull MinesweeperBoard board) { super(new BoardController(), new MinesweeperController(), board.getDimension()); diff --git a/src/main/java/edu/rpi/legup/puzzle/minesweeper/elements/Bomb.java b/src/main/java/edu/rpi/legup/puzzle/minesweeper/elements/BombTile.java similarity index 61% rename from src/main/java/edu/rpi/legup/puzzle/minesweeper/elements/Bomb.java rename to src/main/java/edu/rpi/legup/puzzle/minesweeper/elements/BombTile.java index 6fe86dcee..90bd8fb90 100644 --- a/src/main/java/edu/rpi/legup/puzzle/minesweeper/elements/Bomb.java +++ b/src/main/java/edu/rpi/legup/puzzle/minesweeper/elements/BombTile.java @@ -1,8 +1,8 @@ package edu.rpi.legup.puzzle.minesweeper.elements; import edu.rpi.legup.model.elements.NonPlaceableElement; -public class Bomb extends NonPlaceableElement{ - public Bomb() { - super("MINE-UNPL-0001", "Bomb", "A bomb", "edu/rpi/legup/images/nurikabe/tiles/NumberTile.png"); +public class BombTile extends NonPlaceableElement{ + public BombTile() { + super("MINE-UNPL-0001", "Bomb", "A bomb", "edu/rpi/legup/images/minesweeper/tiles/Bomb.png"); } } diff --git a/src/main/java/edu/rpi/legup/puzzle/minesweeper/elements/EmptyTile.java b/src/main/java/edu/rpi/legup/puzzle/minesweeper/elements/EmptyTile.java new file mode 100644 index 000000000..dad1593ca --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/minesweeper/elements/EmptyTile.java @@ -0,0 +1,10 @@ +package edu.rpi.legup.puzzle.minesweeper.elements; + +import edu.rpi.legup.model.elements.PlaceableElement; + +public class EmptyTile extends PlaceableElement { + + public EmptyTile() { + super("MINE-PLAC-0002", "Empty", "An empty tile", "edu/rpi/legup/images/minesweeper/tiles/Empty.png"); + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/minesweeper/elements/Flag.java b/src/main/java/edu/rpi/legup/puzzle/minesweeper/elements/FlagTile.java similarity index 53% rename from src/main/java/edu/rpi/legup/puzzle/minesweeper/elements/Flag.java rename to src/main/java/edu/rpi/legup/puzzle/minesweeper/elements/FlagTile.java index 9e9b53bae..b6d44d11a 100644 --- a/src/main/java/edu/rpi/legup/puzzle/minesweeper/elements/Flag.java +++ b/src/main/java/edu/rpi/legup/puzzle/minesweeper/elements/FlagTile.java @@ -1,8 +1,8 @@ package edu.rpi.legup.puzzle.minesweeper.elements; import edu.rpi.legup.model.elements.PlaceableElement; -public class Flag extends PlaceableElement{ - public Flag() { - super("NURI-PLAC-0001", "Flag", "The flag", "edu/rpi/legup/images/nurikabe/tiles/BlackTile.png"); +public class FlagTile extends PlaceableElement{ + public FlagTile() { + super("MINE-PLAC-0001", "Flag", "The flag", "edu/rpi/legup/images/nurikabe/tiles/BlackTile.png"); } } diff --git a/src/main/java/edu/rpi/legup/puzzle/minesweeper/elements/UnsetTile.java b/src/main/java/edu/rpi/legup/puzzle/minesweeper/elements/UnsetTile.java new file mode 100644 index 000000000..1899a4fd5 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/minesweeper/elements/UnsetTile.java @@ -0,0 +1,11 @@ +package edu.rpi.legup.puzzle.minesweeper.elements; + +import edu.rpi.legup.model.elements.NonPlaceableElement; + +public class UnsetTile extends NonPlaceableElement { + + public UnsetTile() { + super("MINE-UNPL-0002", "Unset", "An unset tile", "edu/rpi/legup/images/minesweeper/tiles/Unset.png"); + } + +} diff --git a/src/main/java/edu/rpi/legup/puzzle/minesweeper/elements/minesweeper_elements_reference_sheet.txt b/src/main/java/edu/rpi/legup/puzzle/minesweeper/elements/minesweeper_elements_reference_sheet.txt new file mode 100644 index 000000000..08ce23f59 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/minesweeper/elements/minesweeper_elements_reference_sheet.txt @@ -0,0 +1,4 @@ +MINE-UNPL-0001 : BombTile +MINE-PLAC-0001 : FlagTile +MINE-PLAC-0002 : EmptyTile +MINE-UNPL-0002 : UnsetTile \ No newline at end of file diff --git a/src/main/java/edu/rpi/legup/puzzle/minesweeper/rules/BombOrFilledCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/minesweeper/rules/BombOrFilledCaseRule.java index f7c42dc6f..bad89b4a4 100644 --- a/src/main/java/edu/rpi/legup/puzzle/minesweeper/rules/BombOrFilledCaseRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/minesweeper/rules/BombOrFilledCaseRule.java @@ -5,7 +5,12 @@ import edu.rpi.legup.model.gameboard.PuzzleElement; import edu.rpi.legup.model.rules.CaseRule; import edu.rpi.legup.model.tree.TreeTransition; +import edu.rpi.legup.puzzle.minesweeper.MinesweeperBoard; +import edu.rpi.legup.puzzle.minesweeper.MinesweeperCell; +import edu.rpi.legup.puzzle.minesweeper.MinesweeperTileData; +import edu.rpi.legup.puzzle.minesweeper.MinesweeperTileType; +import java.util.ArrayList; import java.util.List; public class BombOrFilledCaseRule extends CaseRule { @@ -18,16 +23,64 @@ public BombOrFilledCaseRule() { @Override public CaseBoard getCaseBoard(Board board) { - return null; + MinesweeperBoard minesweeperBoard = (MinesweeperBoard) board.copy(); + CaseBoard caseBoard = new CaseBoard(minesweeperBoard, this); + minesweeperBoard.setModifiable(false); + for (PuzzleElement data : minesweeperBoard.getPuzzleElements()) { + MinesweeperCell cell = (MinesweeperCell) data; + if (cell.getData().isUnset()) { + caseBoard.addPickableElement(data); + } + } + return caseBoard; } @Override public List getCases(Board board, PuzzleElement puzzleElement) { - return null; + ArrayList cases = new ArrayList<>(); + + Board case1 = board.copy(); + MinesweeperCell cell1 = (MinesweeperCell) case1.getPuzzleElement(puzzleElement); + cell1.setData(MinesweeperTileData.bomb()); + case1.addModifiedData(cell1); + cases.add(case1); + + Board case2 = board.copy(); + MinesweeperCell cell2 = (MinesweeperCell) case2.getPuzzleElement(puzzleElement); + cell2.setData(MinesweeperTileData.empty()); + case2.addModifiedData(cell2); + cases.add(case2); + return cases; } @Override public String checkRuleRaw(TreeTransition transition) { + List childTransitions = transition.getParents().get(0).getChildren(); + if (childTransitions.size() != 2) { + return super.getInvalidUseOfRuleMessage() + ": This case rule must have 2 children."; + } + + TreeTransition case1 = childTransitions.get(0); + TreeTransition case2 = childTransitions.get(1); + if (case1.getBoard().getModifiedData().size() != 1 + || case2.getBoard().getModifiedData().size() != 1) { + return super.getInvalidUseOfRuleMessage() + + ": This case rule must have 1 modified cell for each case."; + } + + MinesweeperCell mod1 = (MinesweeperCell) case1.getBoard().getModifiedData().iterator().next(); + MinesweeperCell mod2 = (MinesweeperCell) case2.getBoard().getModifiedData().iterator().next(); + if (!mod1.getLocation().equals(mod2.getLocation())) { + return super.getInvalidUseOfRuleMessage() + + ": This case rule must modify the same cell for each case."; + } + + if (!((mod1.getData().isBomb() && mod2.getData().isEmpty()) + || (mod2.getData().isBomb() && mod1.getData().isEmpty()))) { + return super.getInvalidUseOfRuleMessage() + + ": This case rule must an empty cell and a bomb cell."; + } + return null; } diff --git a/src/main/resources/edu/rpi/legup/images/minesweeper/tiles/Bomb.png b/src/main/resources/edu/rpi/legup/images/minesweeper/tiles/Bomb.png new file mode 100644 index 000000000..dd6bad509 Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/minesweeper/tiles/Bomb.png differ diff --git a/src/main/resources/edu/rpi/legup/legup/config b/src/main/resources/edu/rpi/legup/legup/config index ccd4f5be3..0bfc68914 100644 --- a/src/main/resources/edu/rpi/legup/legup/config +++ b/src/main/resources/edu/rpi/legup/legup/config @@ -39,5 +39,9 @@ qualifiedClassName="edu.rpi.legup.puzzle.skyscrapers.Skyscrapers" fileType=".xml" fileCreationDisabled="false"/> +