diff --git a/src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerBoard.java b/src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerBoard.java index 9877ccc38..01a6ac918 100644 --- a/src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerBoard.java +++ b/src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerBoard.java @@ -10,18 +10,44 @@ public class ThermometerBoard extends GridBoard{ + //an array containing all of our vials on the board private ArrayList vials; + //representations of the number requirements along rows and columns of the board + private ArrayList colNumbers; + private ArrayList rowNumbers; + + //constructors for the boards and variables public ThermometerBoard(int width, int height){ super(width, height); + + //filling the arrays with zeros so they can be properly updated later + colNumbers = new ArrayList<>(); + for (int i = 0; i < width; i++) { + colNumbers.add(0); + } + rowNumbers = new ArrayList<>(); + for (int i = 0; i < height; i++) { + rowNumbers.add(0); + } + vials = new ArrayList<>(); } - public ThermometerBoard(int size){ super(size, size); + + //filling the arrays with zeros so they can be properly updated later + colNumbers = new ArrayList<>(); + rowNumbers = new ArrayList<>(); + for (int i = 0; i < size; i++) { + colNumbers.add(0); + rowNumbers.add(0); + } + vials = new ArrayList<>(); } + //setters and accessors for our array of vials public boolean addVial(ThermometerCell headCell, ThermometerCell tipCell) { if(verifyVial(headCell, tipCell, this)) { vials.add(new Vial(headCell, tipCell, this)); @@ -33,6 +59,36 @@ public ArrayList getVials() { return vials; } + + //our getters for row/col numbers with simple input verification + public boolean setRowNumber(int row, int num) { + //first check is to verify we are updating an element in range + //second check is to verify the new number can be achieved by the puzzle + if (row < rowNumbers.size() && num <= colNumbers.size()){ + rowNumbers.set(row, num); + return true; + } + return false; + } + public boolean setColNumber(int col, int num) { + //first check is to verify we are updating an element in range + //second check is to verify the new number can be achieved by the puzzle + if (col < colNumbers.size() && num <= rowNumbers.size()){ + rowNumbers.set(col, num); + return true; + } + return false; + } + + //basic accessors, probably fine as is + public int getRowNumber(int row){ + return rowNumbers.get(row); + } + public int getColNumber(int col){ + return colNumbers.get(col); + } + + @Override public ThermometerCell getCell(int x, int y){ if(x < 0 || y < 0 || x > dimension.height || y > dimension.width) return null; diff --git a/src/main/java/edu/rpi/legup/puzzle/thermometer/elements/Vial.java b/src/main/java/edu/rpi/legup/puzzle/thermometer/elements/Vial.java index c920fb866..93b7fe491 100644 --- a/src/main/java/edu/rpi/legup/puzzle/thermometer/elements/Vial.java +++ b/src/main/java/edu/rpi/legup/puzzle/thermometer/elements/Vial.java @@ -2,60 +2,102 @@ import edu.rpi.legup.puzzle.thermometer.ThermometerCell; import edu.rpi.legup.puzzle.thermometer.ThermometerBoard; +import edu.rpi.legup.puzzle.thermometer.ThermometerFill; import edu.rpi.legup.puzzle.thermometer.ThermometerType; import edu.rpi.legup.model.elements.PlaceableElement; +import java.awt.*; import java.util.ArrayList; import static java.lang.Math.*; public class Vial { - private final ArrayList cells; + private ArrayList cells; public Vial(ThermometerCell headCell, ThermometerCell tipCell, ThermometerBoard board) { cells = new ArrayList<>(); - fillCells(headCell, tipCell, board); - + fillData(headCell, tipCell, board); } - private void fillCells(ThermometerCell headCell, ThermometerCell tipCell, ThermometerBoard board) { + //function called by the constructor which adds in all of the cells to the array + //as well as updates their type on the board + private void fillData(ThermometerCell headCell, ThermometerCell tipCell, ThermometerBoard board) { //shorthand for useful variables int headX = (int) headCell.getLocation().getX(); int headY = (int) headCell.getLocation().getY(); int tipX = (int) tipCell.getLocation().getX(); int tipY = (int) tipCell.getLocation().getY(); - //checking if the vial travels along the x or y axis - if(headX == tipX) { - int top = min(headY, tipY); - int bottom = max(headY, tipY); - - //Likely is not setting the data the way we think it is - board.getCell(headX, headY).setData(ThermometerType.HEAD.ordinal()); - cells.add(board.getCell(headX, headY)); - for (int i = top + 1; i < bottom - 1; i++){ - board.getCell(headX, i).setData(ThermometerType.SHAFT.ordinal()); - cells.add(board.getCell(headX, i)); + //not totally happy with layout of code but most readable version I can think of atm + //top left coordinate is 0,0 cells are added from head to tip always + //because cells have already been verified by time constructor is called + //we can guarantee that only the x or only the y coordinates wont line up + if(headY < tipY){ + addCell(headX, headY, ThermometerType.HEAD, board); + for (int i = headY + 1; i < tipY - 1; i++) { + addCell(headX, i, ThermometerType.SHAFT, board); } - board.getCell(tipX, tipY).setData(ThermometerType.TIP.ordinal()); - cells.add(board.getCell(tipX, tipY)); - + addCell(tipX, tipY, ThermometerType.TIP, board); + } + else if (tipY < headY) { + addCell(headX, headY, ThermometerType.HEAD, board); + for (int i = headY - 1; i > tipY; i--) { + addCell(headX, i, ThermometerType.SHAFT, board); + } + addCell(tipX, tipY, ThermometerType.TIP, board); + } + else if (headX < tipX){ + addCell(headX, headY, ThermometerType.HEAD, board); + for (int i = headX + 1; i < tipX - 1; i++) { + addCell(i, headY, ThermometerType.SHAFT, board); + } + addCell(tipX, tipY, ThermometerType.TIP, board); } else{ - int top = min(headX, tipX); - int bottom = max(headX, tipX); + addCell(headX, headY, ThermometerType.HEAD, board); + for (int i = headX - 1; i > tipX; i--) { + addCell(i, headY, ThermometerType.SHAFT, board); + } + addCell(tipX, tipY, ThermometerType.TIP, board); + } + + } + + //helper function for adding a single cell + private void addCell(int x, int y, ThermometerType t, ThermometerBoard board){ - board.getCell(headX, headY).setData(ThermometerType.HEAD.ordinal()); - cells.add(board.getCell(headX, headY)); - for (int i = top + 1; i < bottom - 1; i++){ - board.getCell(i, headY).setData(ThermometerType.SHAFT.ordinal()); - cells.add(board.getCell(i, headY)); + //this very likely is not updating the data in the way we want it to + board.getCell(x, y).setData(t.ordinal()); + cells.add(board.getCell(x, y)); + } + + //a basic accessor to check if a cell is contained in vial + public boolean containsCell(ThermometerCell cell){ + for (ThermometerCell c : cells) { + if (c.getLocation() == cell.getLocation()) { + return true; } - board.getCell(tipX, tipY).setData(ThermometerType.TIP.ordinal()); - cells.add(board.getCell(headX, headY)); } + return false; } + //checking for discontinuous flow inside of vial + public boolean continuousFlow(){ + //bool which is true until it runs into an empty/blocked cell in the vial + //if an empty cell in the vial is found while flow is set to false + //we know there is a break in the flow + boolean flow = true; + + for(ThermometerCell c : cells){ + if(c.getFill() != ThermometerFill.FILLED && flow) flow = false; + + if(c.getFill() == ThermometerFill.FILLED && !flow) return false; + } + return true; + } + + + //used before calling the constructor to make sure the vial we are attempting to add is valid public static boolean verifyVial(ThermometerCell headCell, ThermometerCell tipCell, ThermometerBoard board) { //shorthand for useful variables int headX = (int) headCell.getLocation().getX(); diff --git a/src/main/java/edu/rpi/legup/puzzle/thermometer/rules/DiscontinuousMercuryContradictionRule.java b/src/main/java/edu/rpi/legup/puzzle/thermometer/rules/DiscontinuousMercuryContradictionRule.java new file mode 100644 index 000000000..a24e2b403 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/thermometer/rules/DiscontinuousMercuryContradictionRule.java @@ -0,0 +1,53 @@ +package edu.rpi.legup.puzzle.thermometer.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.thermometer.ThermometerBoard; +import edu.rpi.legup.puzzle.thermometer.ThermometerCell; +import edu.rpi.legup.puzzle.thermometer.elements.Vial; + +import java.util.ArrayList; + +public class DiscontinuousMercuryContradictionRule 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 vial"; + + public DiscontinuousMercuryContradictionRule() { + super("DiscontinuousMercury", + "Discontinuous Mercury", + "A vial has a filled cell after an empty or blocked cell", + null); + } + + + //User can click on any cell in a vial with a discontinuous flow + @Override + public String checkContradictionAt(Board board, PuzzleElement puzzleElement) { + //useful variables + ThermometerBoard thermometerBoard = (ThermometerBoard) board; + + ThermometerCell cell = (ThermometerCell) thermometerBoard.getPuzzleElement(puzzleElement); + + ArrayList vials = thermometerBoard.getVials(); + + //finding out which vial contains the specified cell + for (int i = 0; i < vials.size(); i++) { + Vial vial = vials.get(i); + //if a vial contains the clicked on cell + //checking if the vial has a break in the flow + if(vial.containsCell(cell)){ + if(vial.continuousFlow()){ + return super.getNoContradictionMessage() + ": " + this.NO_CONTRADICTION_MESSAGE; + } + else{ + return null; + } + } + } + + //if none of the vials contain the clicked on cell yell at user + return super.getInvalidUseOfRuleMessage() + ": " + this.INVALID_USE_MESSAGE; + } +}