diff --git a/src/main/java/edu/rpi/legup/puzzle/minesweeper/MinesweeperUtilities.java b/src/main/java/edu/rpi/legup/puzzle/minesweeper/MinesweeperUtilities.java index e74979e19..f54a1d825 100644 --- a/src/main/java/edu/rpi/legup/puzzle/minesweeper/MinesweeperUtilities.java +++ b/src/main/java/edu/rpi/legup/puzzle/minesweeper/MinesweeperUtilities.java @@ -1,5 +1,11 @@ package edu.rpi.legup.puzzle.minesweeper; +import edu.rpi.legup.puzzle.fillapix.FillapixBoard; +import edu.rpi.legup.puzzle.fillapix.FillapixCell; +import edu.rpi.legup.puzzle.fillapix.FillapixCellType; +import edu.rpi.legup.puzzle.fillapix.rules.TooFewBlackCellsContradictionRule; +import edu.rpi.legup.puzzle.minesweeper.rules.LessBombsThanFlagContradictionRule; + import java.awt.*; import java.util.Objects; import java.util.stream.IntStream; @@ -95,7 +101,7 @@ public static ArrayList getAdjacentCells(MinesweeperBoard board continue; } MinesweeperCell adjCell = (MinesweeperCell) board.getCell(cellLoc.x + i, cellLoc.y + j); - if (adjCell == null) { + if (adjCell == null || adjCell == cell) { continue; } adjCells.add(adjCell); @@ -137,5 +143,20 @@ private static void recurseCombinations(ArrayList result, int curInde recurseCombinations(result, curIndex+1, maxBlack, numBlack, len, workingArray); } + public static boolean isForcedBomb(MinesweeperBoard board, MinesweeperCell cell) { + + LessBombsThanFlagContradictionRule tooManyBombs = + new LessBombsThanFlagContradictionRule(); + MinesweeperBoard emptyCaseBoard = board.copy(); + MinesweeperCell emptyCell = (MinesweeperCell) emptyCaseBoard.getPuzzleElement(cell); + emptyCell.setCellType(MinesweeperTileData.empty()); + ArrayList adjCells = getAdjacentCells(emptyCaseBoard, emptyCell); + for (MinesweeperCell adjCell : adjCells) { + if (tooManyBombs.checkContradictionAt(emptyCaseBoard, adjCell) == null) { + return true; + } + } + return false; + } } diff --git a/src/main/java/edu/rpi/legup/puzzle/minesweeper/rules/FinishWithBombsDirectRule.java b/src/main/java/edu/rpi/legup/puzzle/minesweeper/rules/FinishWithBombsDirectRule.java new file mode 100644 index 000000000..9f5c4279c --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/minesweeper/rules/FinishWithBombsDirectRule.java @@ -0,0 +1,63 @@ +package edu.rpi.legup.puzzle.minesweeper.rules; + +import edu.rpi.legup.model.gameboard.Board; +import edu.rpi.legup.model.gameboard.PuzzleElement; +import edu.rpi.legup.model.rules.DirectRule; +import edu.rpi.legup.model.tree.TreeNode; +import edu.rpi.legup.model.tree.TreeTransition; +import edu.rpi.legup.puzzle.minesweeper.*; + +public class FinishWithBombsDirectRule extends DirectRule { + public FinishWithBombsDirectRule() { + super( + "MINE-BASC-0001", + "Finish with Bombs", + "The remaining unknowns around a flag must be bombs to satisfy the number", + "edu/rpi/legup/images/minesweeper/direct/Fill_Bombs.jpg"); + } + + @Override + public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement) { + MinesweeperBoard board = (MinesweeperBoard) transition.getBoard(); + MinesweeperBoard parentBoard = (MinesweeperBoard) transition.getParents().get(0).getBoard(); + MinesweeperCell cell = (MinesweeperCell) board.getPuzzleElement(puzzleElement); + MinesweeperCell parentCell = (MinesweeperCell) parentBoard.getPuzzleElement(puzzleElement); + + if (!(parentCell.getTileType() == MinesweeperTileType.UNSET + && cell.getTileType() == MinesweeperTileType.BOMB)) { + return super.getInvalidUseOfRuleMessage() + + ": This cell must be black to be applicable with this rule."; + } + + if (MinesweeperUtilities.isForcedBomb(parentBoard, cell)) { + return null; + } else { + return super.getInvalidUseOfRuleMessage() + ": This cell is not forced to be black"; + } + } + + /** + * Creates a transition {@link Board} that has this rule applied to it using the {@link + * TreeNode}. + * + * @param node tree node used to create default transition board + * @return default board or null if this rule cannot be applied to this tree node + */ + @Override + public Board getDefaultBoard(TreeNode node) { + MinesweeperBoard minesweeperBoard = (MinesweeperBoard) node.getBoard().copy(); + for (PuzzleElement element : minesweeperBoard.getPuzzleElements()) { + MinesweeperCell cell = (MinesweeperCell) element; + if (cell.getTileType() == MinesweeperTileType.UNSET + && MinesweeperUtilities.isForcedBomb((MinesweeperBoard) node.getBoard(), cell)) { + cell.setCellType(MinesweeperTileData.bomb()); + minesweeperBoard.addModifiedData(cell); + } + } + if (minesweeperBoard.getModifiedData().isEmpty()) { + return null; + } else { + return minesweeperBoard; + } + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/minesweeper/rules/LessBombsThanFlagContradictionRule.java b/src/main/java/edu/rpi/legup/puzzle/minesweeper/rules/LessBombsThanFlagContradictionRule.java index 0cc1f6324..5d809d527 100644 --- a/src/main/java/edu/rpi/legup/puzzle/minesweeper/rules/LessBombsThanFlagContradictionRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/minesweeper/rules/LessBombsThanFlagContradictionRule.java @@ -3,12 +3,10 @@ import edu.rpi.legup.model.gameboard.Board; import edu.rpi.legup.model.gameboard.PuzzleElement; import edu.rpi.legup.model.rules.ContradictionRule; -import edu.rpi.legup.puzzle.nurikabe.NurikabeBoard; -import edu.rpi.legup.puzzle.nurikabe.NurikabeCell; -import edu.rpi.legup.puzzle.nurikabe.NurikabeType; -import edu.rpi.legup.puzzle.nurikabe.NurikabeUtilities; +import edu.rpi.legup.puzzle.minesweeper.*; import edu.rpi.legup.utility.DisjointSets; +import java.util.ArrayList; import java.util.Set; public class LessBombsThanFlagContradictionRule extends ContradictionRule { @@ -23,8 +21,30 @@ public LessBombsThanFlagContradictionRule() { @Override public String checkContradictionAt(Board board, PuzzleElement puzzleElement) { - - return null; + MinesweeperBoard minesweeperBoard = (MinesweeperBoard) board; + MinesweeperCell cell = (MinesweeperCell) minesweeperBoard.getPuzzleElement(puzzleElement); + + int cellNum = cell.getTileNumber(); + if (cellNum <= 0 || cellNum >= 9) { + return super.getNoContradictionMessage(); + } + int numEmpty = 0; + int numAdj = 0; + ArrayList adjCells = MinesweeperUtilities.getAdjacentCells(minesweeperBoard, cell); + for (MinesweeperCell adjCell : adjCells) { + numAdj++; + if (adjCell.getTileType() == MinesweeperTileType.EMPTY && adjCell != cell) { + numEmpty++; + } + } + System.out.println(numEmpty); + System.out.println(numAdj); + System.out.println(cellNum); + if (numEmpty > (numAdj-cellNum)) { + return null; + } + + return super.getNoContradictionMessage(); } diff --git a/src/main/java/edu/rpi/legup/puzzle/minesweeper/rules/SatisfyFlagCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/minesweeper/rules/SatisfyFlagCaseRule.java index 257cfb41b..e3cd382ed 100644 --- a/src/main/java/edu/rpi/legup/puzzle/minesweeper/rules/SatisfyFlagCaseRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/minesweeper/rules/SatisfyFlagCaseRule.java @@ -27,7 +27,7 @@ public CaseBoard getCaseBoard(Board board) { minesweeperBoard.setModifiable(false); for (PuzzleElement data : minesweeperBoard.getPuzzleElements()) { MinesweeperCell cell = (MinesweeperCell) data; - if (cell.getTileNumber() >= 0 && cell.getTileNumber() <= 8 && MinesweeperUtilities.hasEmptyAdjacent(minesweeperBoard, cell)) { + if (cell.getTileNumber() > 0 && cell.getTileNumber() <= 8 && MinesweeperUtilities.hasEmptyAdjacent(minesweeperBoard, cell)) { caseBoard.addPickableElement(data); } } diff --git a/src/main/resources/edu/rpi/legup/images/minesweeper/direct/Fill_Bombs.jpg b/src/main/resources/edu/rpi/legup/images/minesweeper/direct/Fill_Bombs.jpg new file mode 100644 index 000000000..8214972ac Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/minesweeper/direct/Fill_Bombs.jpg differ