Separated node class from DFS class.
This commit is contained in:
parent
de3b3a614a
commit
be19db1f9b
@ -0,0 +1,72 @@
|
||||
package ca.recrown.islandsurvivalcraft.pathfinding;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class DFSNode implements Comparable<DFSNode> {
|
||||
private DFSNode goal;
|
||||
public DFSNode[] child;
|
||||
private DFSNode parent;
|
||||
private int x;
|
||||
private int y;
|
||||
|
||||
public DFSNode(DFSNode parent, int x, int y, DFSNode goal) {
|
||||
child = new DFSNode[4];
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.parent = parent;
|
||||
this.goal = goal;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public DFSNode getGoal() {
|
||||
return goal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(DFSNode o) {
|
||||
if (goal == null) return 0;
|
||||
return Math.round(distanceToGoal(goal) - o.distanceToGoal(goal));
|
||||
}
|
||||
|
||||
public DFSNode getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public float distanceToGoal(DFSNode goal) {
|
||||
float distanceX = goal.x - this.x;
|
||||
float distanceY = goal.y - this.y;
|
||||
float distance = (float) Math.sqrt(distanceX * distanceX + distanceY * distanceY);
|
||||
return distance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof DFSNode) {
|
||||
DFSNode comp = (DFSNode) obj;
|
||||
if (comp.x == this.x && comp.y == this.y) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(x, y);
|
||||
}
|
||||
|
||||
public void copyTo(DFSNode node) {
|
||||
node.child = child;
|
||||
node.parent = parent;
|
||||
node.x = x;
|
||||
node.y = y;
|
||||
node.goal = goal;
|
||||
}
|
||||
}
|
@ -1,21 +1,19 @@
|
||||
package ca.recrown.islandsurvivalcraft.pathfinding;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.PriorityQueue;
|
||||
import java.util.Queue;
|
||||
|
||||
import org.apache.commons.lang.NullArgumentException;
|
||||
|
||||
public class DepthFirstSearch {
|
||||
private Queue<Node> queue;
|
||||
private Queue<DFSNode> queue;
|
||||
private CoordinateValidatable coordValidatable;
|
||||
private Node startNode;
|
||||
private Node endNode;
|
||||
private HashSet<Node> checkedNodes;
|
||||
private DFSNode startNode;
|
||||
private DFSNode endNode;
|
||||
private HashSet<DFSNode> checkedNodes;
|
||||
private int maxNodesSearched = -1;
|
||||
private int foundX;
|
||||
private int foundY;
|
||||
private DFSNode foundNode;
|
||||
|
||||
public DepthFirstSearch() {
|
||||
checkedNodes = new HashSet<>();
|
||||
@ -39,22 +37,18 @@ public class DepthFirstSearch {
|
||||
|
||||
public void setValidatable(CoordinateValidatable validatable) {
|
||||
this.coordValidatable = validatable;
|
||||
}
|
||||
}
|
||||
|
||||
public void setStartPosition(int x, int y) {
|
||||
startNode = new Node(null, x, y);
|
||||
startNode = new DFSNode(null, x, y, endNode);
|
||||
}
|
||||
|
||||
public void setDirectionPosition(int x, int y) {
|
||||
endNode = new Node(null, x, y);
|
||||
endNode = new DFSNode(null, x, y, endNode);
|
||||
}
|
||||
|
||||
public int getEndX() {
|
||||
return foundX;
|
||||
}
|
||||
|
||||
public int getEndY() {
|
||||
return foundY;
|
||||
public DFSNode getFoundNode() {
|
||||
return foundNode;
|
||||
}
|
||||
|
||||
public void deleteTree() {
|
||||
@ -63,50 +57,55 @@ public class DepthFirstSearch {
|
||||
}
|
||||
|
||||
public boolean buildPathToEndNode() {
|
||||
if (coordValidatable == null) throw new IllegalStateException("Need to set a validator.");
|
||||
if (startNode == null) throw new IllegalStateException("Need to set the starting position.");
|
||||
if (coordValidatable == null)
|
||||
throw new IllegalStateException("Need to set a validator.");
|
||||
if (startNode == null)
|
||||
throw new IllegalStateException("Need to set the starting position.");
|
||||
|
||||
return findTarget(new CoordinateTargetValidatable() {
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isCoordinateTarget(int x, int y) {
|
||||
return endNode.x == x && endNode.y == y;
|
||||
return endNode.getX() == x && endNode.getY() == y;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the end node.
|
||||
* If an end node is set, it will try going in that direction first.
|
||||
* Will not set end node if one wasn't found,
|
||||
* therefore, previous end node data is kept.
|
||||
* Finds the end node. If an end node is set, it will try going in that
|
||||
* direction first. Will not set end node if one wasn't found, therefore,
|
||||
* previous end node data is kept.
|
||||
*
|
||||
* @param targetValidator
|
||||
* @return
|
||||
*/
|
||||
public boolean findTarget(CoordinateTargetValidatable targetValidator) {
|
||||
if (coordValidatable == null) throw new IllegalStateException("Need to set a validator.");
|
||||
if (targetValidator == null) throw new NullArgumentException("targetValidator");
|
||||
if (startNode == null) throw new IllegalStateException("Need to set the starting position.");
|
||||
if (coordValidatable == null)
|
||||
throw new IllegalStateException("Need to set a validator.");
|
||||
if (targetValidator == null)
|
||||
throw new NullArgumentException("targetValidator");
|
||||
if (startNode == null)
|
||||
throw new IllegalStateException("Need to set the starting position.");
|
||||
|
||||
queue.clear();
|
||||
checkedNodes.clear();
|
||||
Node begin = startNode;
|
||||
DFSNode begin = startNode;
|
||||
queue.add(begin);
|
||||
while (!queue.isEmpty()) {
|
||||
Node n = queue.poll();
|
||||
if (maxNodesSearched != -1 && checkedNodes.size() > maxNodesSearched) return false;
|
||||
if (checkedNodes.add(n) && coordValidatable.validate(n.x, n.y)) {
|
||||
n.child[0] = new Node(n, n.x + 1, n.y);
|
||||
n.child[1] = new Node(n, n.x - 1, n.y);
|
||||
n.child[2] = new Node(n, n.x, n.y + 1);
|
||||
n.child[3] = new Node(n, n.x, n.y - 1);
|
||||
if (targetValidator.isCoordinateTarget(n.x, n.y)) {
|
||||
foundX = n.x;
|
||||
foundY = n.y;
|
||||
DFSNode n = queue.poll();
|
||||
if (maxNodesSearched != -1 && checkedNodes.size() > maxNodesSearched)
|
||||
return false;
|
||||
if (checkedNodes.add(n) && coordValidatable.validate(n.getX(), n.getY())) {
|
||||
n.child[0] = new DFSNode(n, n.getX() + 1, n.getY(), endNode);
|
||||
n.child[1] = new DFSNode(n, n.getX() - 1, n.getY(), endNode);
|
||||
n.child[2] = new DFSNode(n, n.getX(), n.getY() + 1, endNode);
|
||||
n.child[3] = new DFSNode(n, n.getX(), n.getY() - 1, endNode);
|
||||
if (targetValidator.isCoordinateTarget(n.getX(), n.getY())) {
|
||||
foundNode = new DFSNode(n.getParent(), n.getX(), n.getY(), null);
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < n.child.length; i++) {
|
||||
Node child = n.child[i];
|
||||
DFSNode child = n.child[i];
|
||||
queue.add(child);
|
||||
}
|
||||
}
|
||||
@ -117,47 +116,4 @@ public class DepthFirstSearch {
|
||||
public int getSearchedCount() {
|
||||
return checkedNodes.size();
|
||||
}
|
||||
private class Node implements Comparable<Node> {
|
||||
public Node[] child;
|
||||
public Node parent;
|
||||
public int x;
|
||||
public int y;
|
||||
|
||||
public Node(Node parent, int x, int y) {
|
||||
this.parent = parent;
|
||||
child = new Node[4];
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Node o) {
|
||||
if (endNode == null) return 0;
|
||||
return Math.round(distanceToGoal(endNode) - o.distanceToGoal(endNode));
|
||||
}
|
||||
|
||||
|
||||
public float distanceToGoal(Node goal) {
|
||||
float distanceX = goal.x - this.x;
|
||||
float distanceY = goal.y - this.y;
|
||||
float distance = (float) Math.sqrt(distanceX * distanceX + distanceY * distanceY);
|
||||
return distance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof Node) {
|
||||
Node comp = (Node) obj;
|
||||
if (comp.x == this.x && comp.y == this.y) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(x, y);
|
||||
}
|
||||
}
|
||||
}
|
@ -146,8 +146,8 @@ public class DepthFirstSearchTest {
|
||||
dfs.setStartPosition(3, 0);
|
||||
|
||||
assertTrue(dfs.findTarget(validator));
|
||||
assertEquals(1, dfs.getEndX());
|
||||
assertEquals(2, dfs.getEndY());
|
||||
assertEquals(1, dfs.getFoundNode().getX());
|
||||
assertEquals(2, dfs.getFoundNode().getY());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -158,8 +158,8 @@ public class DepthFirstSearchTest {
|
||||
dfs.setStartPosition(0, 0);
|
||||
|
||||
assertTrue(dfs.findTarget(validator));
|
||||
assertEquals(0, dfs.getEndX());
|
||||
assertEquals(3, dfs.getEndY());
|
||||
assertEquals(0, dfs.getFoundNode().getX());
|
||||
assertEquals(3, dfs.getFoundNode().getY());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -169,8 +169,8 @@ public class DepthFirstSearchTest {
|
||||
dfs.setStartPosition(3, 0);
|
||||
|
||||
assertTrue(dfs.findTarget(validator));
|
||||
assertEquals(95, dfs.getEndX());
|
||||
assertEquals(49, dfs.getEndY());
|
||||
assertEquals(95, dfs.getFoundNode().getX());
|
||||
assertEquals(49, dfs.getFoundNode().getY());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -199,8 +199,8 @@ public class DepthFirstSearchTest {
|
||||
dfs.setStartPosition(0, 0);
|
||||
|
||||
assertTrue(dfs.findTarget(validator));
|
||||
assertEquals(26, dfs.getEndX());
|
||||
assertEquals(32, dfs.getEndY());
|
||||
assertEquals(26, dfs.getFoundNode().getX());
|
||||
assertEquals(32, dfs.getFoundNode().getY());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -220,7 +220,7 @@ public class DepthFirstSearchTest {
|
||||
dfs.setDirectionPosition(42, 84);
|
||||
|
||||
assertTrue(dfs.findTarget(validator));
|
||||
assertEquals(95, dfs.getEndX());
|
||||
assertEquals(49, dfs.getEndY());
|
||||
assertEquals(95, dfs.getFoundNode().getX());
|
||||
assertEquals(49, dfs.getFoundNode().getY());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user