From ee4b707a3fa86fe72a38d3576b873c918cbad16a Mon Sep 17 00:00:00 2001 From: vockek Date: Tue, 12 Mar 2024 17:01:34 -0400 Subject: [PATCH] Revert "temp" This reverts commit b4c8ed9b91fe5ba822df71799c68c017dd42f074. --- .../minesweeper/MinesweeperUtilities.java | 113 ++++++++++-------- 1 file changed, 62 insertions(+), 51 deletions(-) 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 81a7694ec..26e2704f1 100644 --- a/src/main/java/edu/rpi/legup/puzzle/minesweeper/MinesweeperUtilities.java +++ b/src/main/java/edu/rpi/legup/puzzle/minesweeper/MinesweeperUtilities.java @@ -1,67 +1,78 @@ package edu.rpi.legup.puzzle.minesweeper; import java.awt.*; -import java.util.*; +import java.util.Objects; +import java.util.stream.IntStream; +import java.util.stream.Stream; -public class MinesweeperUtilities { - public static boolean hasEmptyAdjacent(MinesweeperBoard board, MinesweeperCell cell) { - ArrayList adjCells = getAdjacentCells(board, cell); - for (MinesweeperCell adjCell : adjCells) { - if (adjCell.getTileType() == MinesweeperTileType.UNSET) { - return true; - } - } - return false; +public final class MinesweeperUtilities { + + private static final int SURROUNDING_CELL_MIN_INDEX = 0; + private static final int SURROUNDING_CELL_MAX_INDEX = 9; + + public static Stream getSurroundingCells(MinesweeperBoard board, MinesweeperCell cell) { + final Point loc = cell.getLocation(); + final int height = board.getHeight(); + final int width = board.getWidth(); + final int x = (int) loc.getX(); + final int y = (int) loc.getY(); + // IntStream of 0-9 to represent 2D matrix of surrounding elements, + // this maps from 0,0 to 2,2 so everything needs to be shifted + // left 1 and up 1 to become + // -1,1 to 1,1 + // and 5 is skipped because we want to ignore 1,1 + return IntStream.range(SURROUNDING_CELL_MIN_INDEX, SURROUNDING_CELL_MAX_INDEX) + // skip 0,0 element + .filter(i -> i != (SURROUNDING_CELL_MAX_INDEX - SURROUNDING_CELL_MIN_INDEX) / 2) + .mapToObj(index -> { + final int newX = index / 3 - 1 + x; + final int newY = index % 3 - 1 + y; + // only keep valid locations + if (newX < 0 || newY < 0 || newX >= width || newY >= height) { + return null; + } + return board.getCell(newX, newY); + }) + .filter(Objects::nonNull); } - public static ArrayList getAdjacentCells(MinesweeperBoard board, MinesweeperCell cell) { - ArrayList adjCells = new ArrayList(); - Point cellLoc = cell.getLocation(); - for (int i=-1; i <= 1; i++) { - for (int j=-1; j <= 1; j++) { - if (cellLoc.getX() + i < 0 || cellLoc.y + j < 0 || cellLoc.x + i >= board.getWidth() || cellLoc.y + j >= board.getHeight()) { - continue; - } - MinesweeperCell adjCell = (MinesweeperCell) board.getCell(cellLoc.x + i, cellLoc.y + j); - if (adjCell == null) { - continue; - } - adjCells.add(adjCell); - } - } - return adjCells; + public static int countSurroundingType(MinesweeperBoard board, MinesweeperCell cell, MinesweeperTileType type) { + final Stream stream = getSurroundingCells(board, cell) + .map(MinesweeperCell::getData); + return (int) (switch (type) { + case UNSET -> stream.filter(MinesweeperTileData::isUnset); + case BOMB -> stream.filter(MinesweeperTileData::isBomb); + case EMPTY -> stream.filter(MinesweeperTileData::isEmpty); + case FLAG -> stream.filter(MinesweeperTileData::isFlag); + }).count(); } - public static ArrayList getCombinations(int chosenNumItems, int totalNumItems) { - ArrayList combinations = new ArrayList(); + public static int countSurroundingBombs(MinesweeperBoard board, MinesweeperCell cell) { + return countSurroundingType(board, cell, MinesweeperTileType.BOMB); + } - // calculate all combinations - boolean[] array = new boolean[totalNumItems]; - recurseCombinations(combinations, 0, chosenNumItems, 0, totalNumItems, array); + public static int countSurroundingUnset(MinesweeperBoard board, MinesweeperCell cell) { + return countSurroundingType(board, cell, MinesweeperTileType.UNSET); + } - return combinations; + public static int countSurroundingEmpty(MinesweeperBoard board, MinesweeperCell cell) { + return countSurroundingType(board, cell, MinesweeperTileType.EMPTY); } - private static void recurseCombinations(ArrayList result, int curIndex, int maxBlack, int numBlack, int len, boolean[] workingArray) { - if (curIndex == len) { - // complete, but not valid solution - if (numBlack != maxBlack) { - return; - } - // complete and valid solution - result.add(workingArray.clone()); - return; - } - // there is no chance of completing the required number of solutions, so quit - if (len - curIndex < maxBlack - numBlack) { - return; - } + public static int countSurroundingFlags(MinesweeperBoard board, MinesweeperCell cell) { + return countSurroundingType(board, cell, MinesweeperTileType.FLAG); + } - if (numBlack < maxBlack) { - workingArray[curIndex] = true; - recurseCombinations(result, curIndex+1, maxBlack, numBlack+1, len, workingArray); + /** + * + * @return how many bombs are left that need to be placed + * around {@code cell} which must be a flag + */ + public int countNeededBombsFromFlag(MinesweeperBoard board, MinesweeperCell cell) { + if (!cell.getData().isFlag()) { + throw new IllegalArgumentException("Bombs are only needed surrounding flags"); } - workingArray[curIndex] = false; - recurseCombinations(result, curIndex+1, maxBlack, numBlack, len, workingArray); + return cell.getData().data() - countSurroundingBombs(board, cell); } + }