Finished tests
This commit is contained in:
parent
d014b9f686
commit
d2c1cb698c
@ -3,13 +3,15 @@ package search.breadthfirstsearch;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
public class EightPuzzleNode implements Node
|
public class EightPuzzleNode implements Node
|
||||||
{
|
{
|
||||||
private int[][] state;
|
private int[][] state;
|
||||||
|
|
||||||
public EightPuzzleNode(int[][] state) {
|
public EightPuzzleNode(int[][] state)
|
||||||
|
{
|
||||||
if (!isValidState(state))
|
if (!isValidState(state))
|
||||||
{
|
{
|
||||||
throw new IllegalArgumentException("Allowed numbers are only 0-8 and they must exist uniquely.");
|
throw new IllegalArgumentException("Allowed numbers are only 0-8 and they must exist uniquely.");
|
||||||
@ -19,44 +21,137 @@ public class EightPuzzleNode implements Node
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isTargetReached(Node target) {
|
public boolean isTargetReached(Node target)
|
||||||
|
{
|
||||||
return Arrays.equals(this.state, ((EightPuzzleNode) target).state);
|
return Arrays.equals(this.state, ((EightPuzzleNode) target).state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Node> generateSuccessors() {
|
public List<Node> generateSuccessors()
|
||||||
ArrayList<Node> successors = new ArrayList<>();
|
{
|
||||||
|
var successors = new ArrayList<Node>();
|
||||||
|
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;
|
return successors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int[][] getState()
|
||||||
|
{
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isValidState(int[][] state)
|
private boolean isValidState(int[][] state)
|
||||||
{
|
{
|
||||||
int[] numbers = Arrays.stream(state).flatMapToInt(IntStream::of).toArray();
|
var numbers = Arrays.stream(state).flatMapToInt(IntStream::of).toArray();
|
||||||
int[] countOfNumbers = new int[9];
|
|
||||||
|
|
||||||
for (int i : numbers)
|
return numbersAreInAllowedRange(numbers) && numbersAreUnique(numbers);
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
countOfNumbers[i]++;
|
|
||||||
}
|
}
|
||||||
catch (ArrayIndexOutOfBoundsException e)
|
|
||||||
|
private boolean numbersAreInAllowedRange(int[] numbers)
|
||||||
{
|
{
|
||||||
return false;
|
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++)
|
||||||
|
{
|
||||||
|
for (int col = 0; col < this.state[row].length; col++)
|
||||||
|
{
|
||||||
|
if (state[row][col] == 0)
|
||||||
|
{
|
||||||
|
return new IntPair(row, col);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i : countOfNumbers)
|
return null;
|
||||||
{
|
|
||||||
if (i == 0 || i > 1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
private int[][] copyOfState()
|
||||||
|
{
|
||||||
|
var copy = new int[3][3];
|
||||||
|
|
||||||
|
for (int y = 0; y < copy.length; y++)
|
||||||
|
{
|
||||||
|
System.arraycopy(this.state[y], 0, copy[y], 0, copy.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
14
test/search/breadthfirstsearch/BreadthFirstSearchTest.java
Normal file
14
test/search/breadthfirstsearch/BreadthFirstSearchTest.java
Normal file
@ -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()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -3,10 +3,9 @@ package search.breadthfirstsearch;
|
|||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
class EightPuzzleNodeTest
|
class EightPuzzleNodeTest
|
||||||
{
|
{
|
||||||
@Test
|
@Test
|
||||||
@ -84,4 +83,45 @@ class EightPuzzleNodeTest
|
|||||||
Assertions.assertFalse(successors.isEmpty());
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user