forked from Bram-Hub/LEGUP
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This reverts commit b4c8ed9.
- Loading branch information
Showing
1 changed file
with
62 additions
and
51 deletions.
There are no files selected for viewing
113 changes: 62 additions & 51 deletions
113
src/main/java/edu/rpi/legup/puzzle/minesweeper/MinesweeperUtilities.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<MinesweeperCell> 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<MinesweeperCell> 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<MinesweeperCell> getAdjacentCells(MinesweeperBoard board, MinesweeperCell cell) { | ||
ArrayList<MinesweeperCell> adjCells = new ArrayList<MinesweeperCell>(); | ||
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<MinesweeperTileData> 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<boolean[]> getCombinations(int chosenNumItems, int totalNumItems) { | ||
ArrayList<boolean[]> combinations = new ArrayList<boolean[]>(); | ||
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<boolean[]> 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); | ||
} | ||
|
||
} |