diff --git a/src/main/java/dotsandboxes/DotsAndBoxesGrid.java b/src/main/java/dotsandboxes/DotsAndBoxesGrid.java index a9e7c5b6639e8a2a8728809d9b17c8d155baf9b6..4b27a408055f3e1fd80b1102e81ea294d0d88fa6 100644 --- a/src/main/java/dotsandboxes/DotsAndBoxesGrid.java +++ b/src/main/java/dotsandboxes/DotsAndBoxesGrid.java @@ -1,35 +1,11 @@ package dotsandboxes; - import java.util.ArrayList; import java.util.Arrays; import java.util.function.Consumer; /** * The state of a dots and boxes grid. - * - * A (4, 3) dots and boxes grid looks like this: - * - * *-*-*-* - * | | | | - * *-*-*-* - * | | | | - * *-*-*-* - * - * Notice that: - * - * - for each row, there is one less horizontal than the number of corner dots - * - for each row, there are as many verticals as there are corner dots - * - for each row, there is one less box than the number of corner dots - * - for each column, there is one less vertical than the number of corner dots. - * - for each column, there are as many horizontals as there are corner dots. - * - for each column, there is one less box than the number of corner dots - * - * For example, in this (4, 3) grid, there are (3, 3) horizontal lines, and (4, 2) vertical lines, and (3, 2) boxes. - * - * We number all lines and boxes by their top-left coordinate. - * - * In Java 14+, we might use a Record class for this, but we're using 11+ as an LTS version, so we don't have that yet. */ public class DotsAndBoxesGrid { @@ -98,7 +74,6 @@ public class DotsAndBoxesGrid { return boxOwners[x][y]; } - /** * Checks whether a box has been fully drawn (all four sides) * @param x coordinate of the left side of the box @@ -110,15 +85,15 @@ public class DotsAndBoxesGrid { return false; } - // A box is complete if the north and south horizontals and the east and west verticals have all been drawn. - // FIXME: You'll need to fix this code (after writing a test first). - return true; + // Check all four sides of the box + return horizontals[x][y] && horizontals[x][y + 1] && + verticals[x][y] && verticals[x + 1][y]; } /** Tries to claim a box for a player. If the box is complete, sets the ownership and returns true. */ private boolean claimBox(int x, int y, int p) { if (boxComplete(x, y)) { - boxOwners[x][y] = player; + boxOwners[x][y] = p; return true; } else { return false; @@ -139,12 +114,14 @@ public class DotsAndBoxesGrid { throw new IndexOutOfBoundsException(String.format("y was %d, which is out of range. Range is 0 to %d", y, height)); } - // FIXME: You need to throw an exception if the line was already drawn. + if (horizontals[x][y]) { + throw new IllegalStateException("Line already drawn!"); + } this.horizontals[x][y] = true; // Try to claim the north or south boxes - boolean claimN = claimBox(x, y-1, player); + boolean claimN = claimBox(x, y - 1, player); boolean claimS = claimBox(x, y, player); if (claimN || claimS) { notifyObservers(); @@ -170,12 +147,14 @@ public class DotsAndBoxesGrid { throw new IndexOutOfBoundsException(String.format("y was %d, which is out of range. Range is 0 to %d", y, height - 1)); } - // You need to throw an exception if the line was already drawn. + if (verticals[x][y]) { + throw new IllegalStateException("Line already drawn!"); + } this.verticals[x][y] = true; - // Try to claim the north or south boxes + // Try to claim the east or west boxes boolean claimE = claimBox(x, y, player); - boolean claimW = claimBox(x-1, y, player); + boolean claimW = claimBox(x - 1, y, player); if (claimE || claimW) { notifyObservers(); return true; @@ -184,14 +163,10 @@ public class DotsAndBoxesGrid { notifyObservers(); return false; } - } public boolean gameComplete() { - // Students who took COSC250 might recognise this style of code. This is Java's version of higher order functions. // The grid is complete if "for all rows, all the boxes in that row have a non-zero owner" return Arrays.stream(boxOwners).allMatch((row) -> Arrays.stream(row).allMatch((owner) -> owner > 0)); } - - } diff --git a/src/test/java/dotsandboxes/DotsAndBoxesGridTest.java b/src/test/java/dotsandboxes/DotsAndBoxesGridTest.java index 1946beda974d180686c65c0259a7b881e9a4eb5a..cf8b6f0be498ecf1c1f88477a93c3399fe2a8d4c 100644 --- a/src/test/java/dotsandboxes/DotsAndBoxesGridTest.java +++ b/src/test/java/dotsandboxes/DotsAndBoxesGridTest.java @@ -2,30 +2,54 @@ package dotsandboxes; import org.junit.jupiter.api.*; import static org.junit.jupiter.api.Assertions.*; -import static org.junit.jupiter.api.Assumptions.*; - import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class DotsAndBoxesGridTest { - /* - * Because Test classes are classes, they can have fields, and can have static fields. - * This field is a logger. Loggers are like a more advanced println, for writing messages out to the console or a log file. - */ private static final Logger logger = LogManager.getLogger(DotsAndBoxesGridTest.class); - /* - * Tests are functions that have an @Test annotation before them. - * The typical format of a test is that it contains some code that does something, and then one - * or more assertions to check that a condition holds. - * - * This is a dummy test just to show that the test suite itself runs - */ @Test public void testTestSuiteRuns() { logger.info("Dummy test to show the test suite runs"); assertTrue(true); } - // FIXME: You need to write tests for the two known bugs in the code. + @Test + public void testSquareCompletion() { + DotsAndBoxesGrid grid = new DotsAndBoxesGrid(3, 3, 2); + + // Draw lines to complete a square + grid.drawHorizontal(0, 0, 1); + grid.drawVertical(0, 0, 1); + grid.drawHorizontal(0, 1, 1); + grid.drawVertical(1, 0, 1); + + // Check if the square is complete + boolean isComplete = grid.boxComplete(0, 0); + + // Log the result + logger.info("Square completion test: " + (isComplete ? "Passed" : "Failed")); + + // Assert that the square is correctly identified as complete + assertTrue(isComplete, "Square should be complete."); + } + + @Test + public void testDuplicateLineDrawing() { + DotsAndBoxesGrid grid = new DotsAndBoxesGrid(3, 3, 2); + + // Draw a line + grid.drawHorizontal(0, 0, 1); + + // Try to draw the same line again and check for an exception + Exception exception = assertThrows(IllegalStateException.class, () -> { + grid.drawHorizontal(0, 0, 1); + }); + + // Log the exception + logger.info("Duplicate line drawing test: " + exception.getMessage()); + + // Assert that the exception message is correct + assertEquals("Line already drawn!", exception.getMessage()); + } }