Skip to content

Commit

Permalink
Merge branch 'minesweeper' into local-brancj
Browse files Browse the repository at this point in the history
  • Loading branch information
willyoung366 authored Dec 2, 2024
2 parents 63cf5a4 + 9e623a0 commit 18a8cb2
Show file tree
Hide file tree
Showing 15 changed files with 533 additions and 6 deletions.
11 changes: 11 additions & 0 deletions puzzles files/minesweeper/5x5 Minesweeper Easy/123456
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Legup version="2.0.0">
<puzzle name="Minesweeper">
<board height="5" width="5">
<cells>

</cells>
</board>
</puzzle>
<solved isSolved="false" lastSaved="--"/>
</Legup>
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package edu.rpi.legup.puzzle.minesweeper;

import edu.rpi.legup.model.gameboard.GridBoard;

import edu.rpi.legup.model.gameboard.PuzzleElement;

import java.util.Set;


public class MinesweeperBoard extends GridBoard {

public MinesweeperBoard(int width, int height) {
Expand Down Expand Up @@ -39,6 +41,4 @@ public MinesweeperBoard copy() {
}
return newMinesweeperBoard;
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ private MinesweeperCellFactory() {}
}
final MinesweeperCell cell =
new MinesweeperCell(MinesweeperTileData.fromData(value), new Point(x, y));

cell.setIndex(y * height + x);
if(value != -2) {
cell.setModifiable(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public class MinesweeperController extends ElementController {
default:
return MinesweeperTileData.empty();
}

}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ public void drawElement(@NotNull Graphics2D graphics2D) {

graphics2D.setFont(FONT);
final FontMetrics metrics = graphics2D.getFontMetrics(FONT);

final int xText = location.x + (size.width - metrics.stringWidth(value)) / 2;
final int yText =
location.y + ((size.height - metrics.getHeight()) / 2) + metrics.getAscent();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public record MinesweeperTileData(MinesweeperTileType type, int data) {
public boolean isUnset() {
return this.data == UNSET_DATA;
}

public boolean isMine() {
return this.data == MINE_DATA;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ public static int countSurroundingType(
})
.count();
}

public static int countSurroundingMines(MinesweeperBoard board, MinesweeperCell cell) {
return countSurroundingType(board, cell, MinesweeperTileType.MINE);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package edu.rpi.legup.puzzle.minesweeper.elements;

import edu.rpi.legup.model.elements.NonPlaceableElement;

public class BombTile extends NonPlaceableElement {
public BombTile() {
super(
"MINE-UNPL-0001",
"Bomb",
"A bomb",
"edu/rpi/legup/images/minesweeper/tiles/Bomb.png");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package edu.rpi.legup.puzzle.minesweeper.elements;

import edu.rpi.legup.model.elements.PlaceableElement;

public class FlagTile extends PlaceableElement {
public FlagTile() {
super(
"MINE-PLAC-0001",
"Flag",
"The flag",
"edu/rpi/legup/images/nurikabe/tiles/BlackTile.png");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package edu.rpi.legup.puzzle.minesweeper.rules;

import edu.rpi.legup.model.gameboard.Board;
import edu.rpi.legup.model.gameboard.CaseBoard;
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 java.util.ArrayList;
import java.util.List;

public class BombOrFilledCaseRule extends CaseRule {

public BombOrFilledCaseRule() {
super(
"MINE-CASE-0001",
"Bomb Or Filled",
"A cell can either be a bomb or filled.\n",
"edu/rpi/legup/images/minesweeper/cases/BombOrFilled.jpg");
}

@Override
public CaseBoard getCaseBoard(Board board) {
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<Board> getCases(Board board, PuzzleElement puzzleElement) {
ArrayList<Board> 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<TreeTransition> 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;
}

@Override
public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement) {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
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;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
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.ContradictionRule;
import edu.rpi.legup.puzzle.minesweeper.*;
import java.util.ArrayList;

public class LessBombsThanFlagContradictionRule extends ContradictionRule {
private final String NO_CONTRADICTION_MESSAGE =
"Does not contain a contradiction at this index";
private final String INVALID_USE_MESSAGE = "Contradiction must be a region";

public LessBombsThanFlagContradictionRule() {
super(
"MINE-CONT-0000",
"Less Bombs Than Flag",
"There can not be less then the number of Bombs around a flag then the specified number\n",
"edu/rpi/legup/images/nurikabe/contradictions/NoNumber.png");
}

@Override
public String checkContradictionAt(Board board, PuzzleElement puzzleElement) {
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<MinesweeperCell> 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();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
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.ContradictionRule;
import edu.rpi.legup.puzzle.minesweeper.MinesweeperBoard;
import edu.rpi.legup.puzzle.minesweeper.MinesweeperCell;
import edu.rpi.legup.puzzle.minesweeper.MinesweeperTileType;
import edu.rpi.legup.puzzle.minesweeper.MinesweeperUtilities;
import java.util.ArrayList;

public class MoreBombsThanFlagContradictionRule extends ContradictionRule {

public MoreBombsThanFlagContradictionRule() {
super(
"MINE-CONT-0001",
"More Bombs Than Flag",
"There can not be more Bombs around a flag than the specified number\n",
"edu/rpi/legup/images/minesweeper/contradictions/Bomb_Surplus.jpg");
}

/**
* Checks whether the transition has a contradiction at the specific puzzleElement index using
* this rule
*
* @param board board to check contradiction
* @param puzzleElement equivalent puzzleElement
* @return null if the transition contains a contradiction at the specified puzzleElement,
* otherwise error message
*/
@Override
public String checkContradictionAt(Board board, PuzzleElement puzzleElement) {
MinesweeperBoard minesweeperBoard = (MinesweeperBoard) board;
MinesweeperCell cell = (MinesweeperCell) minesweeperBoard.getPuzzleElement(puzzleElement);

int cellNum = cell.getTileNumber();
if (cellNum < 0 || cellNum >= 10) {
return super.getNoContradictionMessage();
}
int numBlack = 0;
ArrayList<MinesweeperCell> adjCells =
MinesweeperUtilities.getAdjacentCells(minesweeperBoard, cell);
for (MinesweeperCell adjCell : adjCells) {
if (adjCell.getTileType() == MinesweeperTileType.BOMB) {
numBlack++;
}
}
if (numBlack > cellNum) {
return null;
}

return super.getNoContradictionMessage();
}
}
Loading

0 comments on commit 18a8cb2

Please sign in to comment.