From d2c1cb698c1d20025502112a4471bcc76cb835d5 Mon Sep 17 00:00:00 2001 From: Niklas Birk Date: Sun, 24 Mar 2019 16:41:14 +0100 Subject: [PATCH] Finished tests --- .../breadthfirstsearch/EightPuzzleNode.java | 135 +++++++++++++++--- .../BreadthFirstSearchTest.java | 14 ++ .../EightPuzzleNodeTest.java | 44 +++++- 3 files changed, 171 insertions(+), 22 deletions(-) create mode 100644 test/search/breadthfirstsearch/BreadthFirstSearchTest.java diff --git a/src/search/breadthfirstsearch/EightPuzzleNode.java b/src/search/breadthfirstsearch/EightPuzzleNode.java index 06c14f9..1532ef8 100644 --- a/src/search/breadthfirstsearch/EightPuzzleNode.java +++ b/src/search/breadthfirstsearch/EightPuzzleNode.java @@ -3,13 +3,15 @@ package search.breadthfirstsearch; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Objects; import java.util.stream.IntStream; public class EightPuzzleNode implements Node { private int[][] state; - public EightPuzzleNode(int[][] state) { + public EightPuzzleNode(int[][] state) + { if (!isValidState(state)) { throw new IllegalArgumentException("Allowed numbers are only 0-8 and they must exist uniquely."); @@ -19,44 +21,137 @@ public class EightPuzzleNode implements Node } @Override - public boolean isTargetReached(Node target) { + public boolean isTargetReached(Node target) + { return Arrays.equals(this.state, ((EightPuzzleNode) target).state); } @Override - public List generateSuccessors() { - ArrayList successors = new ArrayList<>(); + public List generateSuccessors() + { + var successors = new ArrayList(); + var emptyPosition = Objects.requireNonNull(detectEmptyPosition()); + int x = emptyPosition.getRight(); + int y = emptyPosition.getLeft(); - successors.add(new EightPuzzleNode(null)); + for (Direction dir : Direction.values()) + { + var newState = copyOfState(); + + try + { + int tmp; + switch (dir) + { + case TOP: + tmp = newState[y-1][x]; + newState[y-1][x] = newState[y][x]; + newState[y][x] = tmp; + successors.add(new EightPuzzleNode(newState)); + break; + case RIGHT: + tmp = newState[y][x+1]; + newState[y][x+1] = newState[y][x]; + newState[y][x] = tmp; + successors.add(new EightPuzzleNode(newState)); + break; + case DOWN: + tmp = newState[y+1][x]; + newState[y+1][x] = newState[y][x]; + newState[y][x] = tmp; + successors.add(new EightPuzzleNode(newState)); + break; + case LEFT: + tmp = newState[y][x-1]; + newState[y][x-1] = newState[y][x]; + newState[y][x] = tmp; + successors.add(new EightPuzzleNode(newState)); + break; + } + } + catch (ArrayIndexOutOfBoundsException ignored) + { + } + } return successors; } + public int[][] getState() + { + return state; + } + private boolean isValidState(int[][] state) { - int[] numbers = Arrays.stream(state).flatMapToInt(IntStream::of).toArray(); - int[] countOfNumbers = new int[9]; + var numbers = Arrays.stream(state).flatMapToInt(IntStream::of).toArray(); - for (int i : numbers) + return numbersAreInAllowedRange(numbers) && numbersAreUnique(numbers); + } + + private boolean numbersAreInAllowedRange(int[] numbers) + { + return Arrays.stream(numbers).min().getAsInt() == 0 && Arrays.stream(numbers).max().getAsInt() == 8; + } + + private boolean numbersAreUnique(int[] numbers) + { + return Arrays.stream(numbers).count() == Arrays.stream(numbers).distinct().count(); + } + + private IntPair detectEmptyPosition() + { + for (int row = 0; row < this.state.length; row++) { - try + for (int col = 0; col < this.state[row].length; col++) { - countOfNumbers[i]++; - } - catch (ArrayIndexOutOfBoundsException e) - { - return false; + if (state[row][col] == 0) + { + return new IntPair(row, col); + } } } - for (int i : countOfNumbers) + return null; + } + + private int[][] copyOfState() + { + var copy = new int[3][3]; + + for (int y = 0; y < copy.length; y++) { - if (i == 0 || i > 1) - { - return false; - } + System.arraycopy(this.state[y], 0, copy[y], 0, copy.length); } - return true; + return copy; + } + + private class IntPair + { + private final int left; + + private final int right; + + public IntPair(int left, int right) + { + this.left = left; + this.right = right; + } + + public int getLeft() + { + return left; + } + public int getRight() + { + return right; + } + + } + private enum Direction + { + TOP, RIGHT, DOWN, LEFT + } } diff --git a/test/search/breadthfirstsearch/BreadthFirstSearchTest.java b/test/search/breadthfirstsearch/BreadthFirstSearchTest.java new file mode 100644 index 0000000..02eeec8 --- /dev/null +++ b/test/search/breadthfirstsearch/BreadthFirstSearchTest.java @@ -0,0 +1,14 @@ +package search.breadthfirstsearch; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class BreadthFirstSearchTest +{ + @Test + void shouldReturnCorrectTarget() + { + + } +} \ No newline at end of file diff --git a/test/search/breadthfirstsearch/EightPuzzleNodeTest.java b/test/search/breadthfirstsearch/EightPuzzleNodeTest.java index 036a5e0..6e0d3c0 100644 --- a/test/search/breadthfirstsearch/EightPuzzleNodeTest.java +++ b/test/search/breadthfirstsearch/EightPuzzleNodeTest.java @@ -3,10 +3,9 @@ package search.breadthfirstsearch; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.util.Arrays; import java.util.List; -import static org.junit.jupiter.api.Assertions.*; - class EightPuzzleNodeTest { @Test @@ -84,4 +83,45 @@ class EightPuzzleNodeTest Assertions.assertFalse(successors.isEmpty()); } + @Test + public void shouldReturnEmptyListOfSuccessors() + { + } + + @Test + public void shouldReturnCorrectSuccessors() + { + int[][] state = { + {7, 1, 6}, + {0, 4, 2}, + {3, 5, 8} + }; + + var node = new EightPuzzleNode(state); + var successors = node.generateSuccessors(); + + Assertions.assertEquals(3, successors.size()); + + int[][] newState1 = { + {0, 1, 6}, + {7, 4, 2}, + {3, 5, 8} + }; + + int[][] newState2 = { + {7, 1, 6}, + {4, 0, 2}, + {3, 5, 8} + }; + + int[][] newState3 = { + {7, 1, 6}, + {3, 4, 2}, + {0, 5, 8} + }; + + Assertions.assertArrayEquals(newState1, ((EightPuzzleNode) successors.get(0)).getState()); + Assertions.assertArrayEquals(newState2, ((EightPuzzleNode) successors.get(1)).getState()); + Assertions.assertArrayEquals(newState3, ((EightPuzzleNode) successors.get(2)).getState()); + } } \ No newline at end of file