From 2486b75755c771d55d2e6d0fbf242777fcb45421 Mon Sep 17 00:00:00 2001 From: t-moe Date: Fri, 24 Jun 2016 21:05:02 +0200 Subject: [PATCH] Moved Pathfinding to own class. This is a preparation for the improved visualization --- src/ch/bfh/sevennotseven/Game.java | 132 +---------- src/ch/bfh/sevennotseven/PathFinder.java | 289 +++++++++++++++++++++++ src/ch/bfh/sevennotseven/Vertex.java | 90 ------- 3 files changed, 294 insertions(+), 217 deletions(-) create mode 100644 src/ch/bfh/sevennotseven/PathFinder.java delete mode 100644 src/ch/bfh/sevennotseven/Vertex.java diff --git a/src/ch/bfh/sevennotseven/Game.java b/src/ch/bfh/sevennotseven/Game.java index c666017..2842d47 100644 --- a/src/ch/bfh/sevennotseven/Game.java +++ b/src/ch/bfh/sevennotseven/Game.java @@ -82,6 +82,7 @@ public class Game { private int numUndos; //number of undos left private Random rand; //instance to get random numbers from private ArrayList updateListeners; //registered listeners + private PathFinder pathfinder; public Game(){ this(7); @@ -96,6 +97,7 @@ public class Game { public Game (int size) { rand = new Random(); // Initialize random object this.updateListeners = new ArrayList(); + this.pathfinder = new PathFinder(); this.reset(size); } @@ -208,53 +210,8 @@ public class Game { * @return Shortest path between src and dst, or null if there is no path */ public List getPath(final Point src, final Point dst){ - - ArrayList vertices = new ArrayList(); // List of vertices - - vertices.add(new Vertex(0, src)); - - // Get a verticies list from the field data - for(int i= 0; i < size; i++){ - for(int j = 0; j < size; j++){ - if(field[i][j] == 0 && (src.x!=i || src.y!=j)){ //field empty and not src - vertices.add(new Vertex(Integer.MAX_VALUE, new Point(i, j))); - } - } - } - - ArrayList allVerticies = new ArrayList(vertices); // List of vertices - - while(!vertices.isEmpty()){ // As long as there are vertices - final Vertex u = findNearestVertex(vertices); - vertices.remove(u); // Remove u from the set of vertices - - final Point[] offsets = { - new Point(0,1), - new Point(0,-1), - new Point(1,0), - new Point(-1,0) - }; - - for(int i = 0; i < 4; i++){ // for each neighbour of u ... - final Point p = u.getPos(); - final Point offs = offsets[i]; - int x = p.x + offs.x; - int y = p.y + offs.y; - if(x<0 || y<0 || x>=size || y>= size) continue; - - final Vertex v = findVertex(x,y, vertices); - //distanz_update(u,v) - if(v!=null){ - int alternative = u.getDist()+1; - if( alternative< v.getDist()) { - v.setDist(alternative); - v.setPrev(u); - } - } - } - } - - return reconstructShortestPath(allVerticies, src,dst); + pathfinder.calculateCosts(field, size, src); + return pathfinder.getPath(dst); } /** @@ -267,14 +224,11 @@ public class Game { if(getAvailUndo() > 0 && lastStates.size() > 0){ lastStates.remove(lastStates.size() - 1).restore(); - numUndos--; - - emitUpdateEvent(); + emitUpdateEvent(); return true; } - return false; } @@ -345,82 +299,6 @@ public class Game { this.populateField(); } - /** - * Finds the nearest vertex to start - * - * @author aaron - * @param vertices - * @return Nearest vertex to the fist element of the given vertices list. - */ - private Vertex findNearestVertex(final List vertices){ - Vertex tmp = vertices.get(0); - - for (int i = 1; i < vertices.size(); i++) { - Vertex n = vertices.get(i); - if(n.getDist() < tmp.getDist()) { - tmp = n; - } - } - - return tmp; - } - - /** - * Helper function for pathfinding. Finds a vertex corresponding to the given coordinate. - * - * @author aaron - * @param x - * @param y - * @param vertices - * @return Vertex with the given position out of a list of vertices. - */ - private Vertex findVertex(int x, int y, final List vertices){ - return findVertex(new Point(x,y), vertices); - } - - /** - * Helper function for pathfinding. Finds a vertex corresponding to the given point. - * - * @author aaron - * @param pos - * @param vertices - * @return Vertex with the given position out of a list of vertices. - */ - private Vertex findVertex(final Point pos, final List vertices){ - for (int i = 0; i < vertices.size(); i++) { - Vertex n = vertices.get(i); - if(n.getPos().equals(pos)) { - return n; - } - } - return null; - } - - /** - * Helper function for pathfinding. Returns shortest path between src and dst in a given set of vertices. - * - * @author aaron - * @param vertices - * @param src - * @param dst - * @return Shortest path between two given points in a list of vertices. - */ - private List reconstructShortestPath(final List vertices, final Point src, final Point dst){ - ArrayList path = new ArrayList(); - path.add(dst); - Vertex u = findVertex(dst, vertices); - if(u==null) { - return null; - } - while(u.getPrev()!=null){ - u= u.getPrev(); - path.add(0, u.getPos()); - } - if(u!=findVertex(src, vertices)){ - return null; - } - return path; - } /** * Calculates the next game step. This method will either call populateField, or it will cleanup blocks * diff --git a/src/ch/bfh/sevennotseven/PathFinder.java b/src/ch/bfh/sevennotseven/PathFinder.java new file mode 100644 index 0000000..a603d1f --- /dev/null +++ b/src/ch/bfh/sevennotseven/PathFinder.java @@ -0,0 +1,289 @@ +package ch.bfh.sevennotseven; + +import java.awt.Point; +import java.util.ArrayList; +import java.util.List; + +/** + * Class which provides helper to find the shortest path between two points + * Based on pseudo-code from https://de.wikipedia.org/wiki/Dijkstra-Algorithmus#Algorithmus_in_Pseudocode + * @author aaron/timo + * + */ +public class PathFinder { + + + /** + * + * Helper class which represents a Node/Vertex of a Graph + * + */ + public static class Vertex { + + /* Class Members */ + private int dist; + private Point pos; + private Vertex prev; + + /** + * Costructor + * + * @author aaron + * @param int dist + * @param Point pos + */ + public Vertex(int dist, Point pos) { + this.dist = dist; + this.pos = pos; + this.prev = null; + } + + /** + * Set the distance + * + * @author aaron + * @param int dist + */ + public void setDist(int dist){ + this.dist = dist; + } + + /** + * Set current position + * + * @author aaron + * @param Point pos + */ + public void setPos(Point pos){ + this.pos = pos; + } + + /** + * Set previous vertex + * + * @author aaron + * @param Vertex prev + */ + public void setPrev(Vertex prev){ + this.prev = prev; + } + + /** + * Get the distance + * + * @author aaron + * @return int dist + */ + public int getDist(){ + return this.dist; + } + + /** + * Get current position + * + * @author aaron + * @return Point pos + */ + public Point getPos(){ + return this.pos; + } + + /** + * Get previous vertex + * + * @author aaron + * @return Vertex prev + */ + public Vertex getPrev(){ + return this.prev; + } + + } + + private ArrayList verticies = null; + private Point lastSrc = null; + private int[][] lastField = null; + private int lastSize; + + + + /** + * Calculates the cost to reach each block starting from point src + * @param field game field + * @param size game size + * @param src starting point + */ + public void calculateCosts(final int[][] field, int size, final Point src) { + ArrayList vertices = new ArrayList(); // List of vertices + + vertices.add(new Vertex(0, src)); + + // Get a verticies list from the field data + for(int i= 0; i < size; i++){ + for(int j = 0; j < size; j++){ + if(field[i][j] == 0 && (src.x!=i || src.y!=j)){ //field empty and not src + vertices.add(new Vertex(Integer.MAX_VALUE, new Point(i, j))); + } + } + } + + ArrayList allVerticies = new ArrayList(vertices); // List of vertices + + while(!vertices.isEmpty()){ // As long as there are vertices + final Vertex u = findNearestVertex(vertices); + vertices.remove(u); // Remove u from the set of vertices + + final Point[] offsets = { + new Point(0,1), + new Point(0,-1), + new Point(1,0), + new Point(-1,0) + }; + + for(int i = 0; i < 4; i++){ // for each neighbour of u ... + final Point p = u.getPos(); + final Point offs = offsets[i]; + int x = p.x + offs.x; + int y = p.y + offs.y; + if(x<0 || y<0 || x>=size || y>= size) continue; + + final Vertex v = findVertex(x,y, vertices); + //distanz_update(u,v) + if(v!=null){ + int alternative = u.getDist()+1; //alternative has cost of current path + 1 (=cost to reach neighbor) + if( alternative< v.getDist()) { + v.setDist(alternative); + v.setPrev(u); + } + } + } + } + + lastSrc = src; + verticies = allVerticies; + lastField = field; + lastSize = size; + } + + + + /** + * Seeks the shortest path to dst without crossing any walls + * @author aaron + * @param dst + * @return Shortest path between src and dst, or null if there is no path + */ + public List getPath(final Point dst){ + if(lastSrc==null || verticies == null || lastField == null) return null; + + ArrayList path = new ArrayList(); + path.add(dst); + Vertex u = findVertex(dst, verticies); + if(u==null) { + return null; + } + while(u.getPrev()!=null){ + u= u.getPrev(); + path.add(0, u.getPos()); + } + if(u!=findVertex(lastSrc, verticies)){ + return null; + } + return path; + } + + /** + * Returns all points which are reachable from src, without crossing any walls + * @return + */ + public List getReachablePoints() { + if(lastSrc==null || verticies == null || lastField == null) return null; + ArrayList res = new ArrayList(); + for(int x=0; x getUnreachablePoints() { + if(lastSrc==null || verticies == null || lastField == null) return null; + ArrayList res = new ArrayList(); + for(int x=0; x vertices){ + Vertex tmp = vertices.get(0); + + for (int i = 1; i < vertices.size(); i++) { + Vertex n = vertices.get(i); + if(n.getDist() < tmp.getDist()) { + tmp = n; + } + } + + return tmp; + } + + /** + * Helper function for pathfinding. Finds a vertex corresponding to the given coordinate. + * + * @author aaron + * @param x + * @param y + * @param vertices + * @return Vertex with the given position out of a list of vertices. + */ + private Vertex findVertex(int x, int y, final List vertices){ + return findVertex(new Point(x,y), vertices); + } + + /** + * Helper function for pathfinding. Finds a vertex corresponding to the given point. + * + * @author aaron + * @param pos + * @param vertices + * @return Vertex with the given position out of a list of vertices. + */ + private Vertex findVertex(final Point pos, final List vertices){ + for (int i = 0; i < vertices.size(); i++) { + Vertex n = vertices.get(i); + if(n.getPos().equals(pos)) { + return n; + } + } + return null; + } + + +} diff --git a/src/ch/bfh/sevennotseven/Vertex.java b/src/ch/bfh/sevennotseven/Vertex.java deleted file mode 100644 index d175341..0000000 --- a/src/ch/bfh/sevennotseven/Vertex.java +++ /dev/null @@ -1,90 +0,0 @@ -package ch.bfh.sevennotseven; - -import java.awt.Point; - -/** - * Vertex class which abstracts vertices as an object. - * - * @author aaron - */ -public class Vertex { - - /* Class Members */ - private int dist; - private Point pos; - private Vertex prev; - - /** - * Costructor - * - * @author aaron - * @param int dist - * @param Point pos - */ - public Vertex(int dist, Point pos) { - this.dist = dist; - this.pos = pos; - this.prev = null; - } - - /** - * Set the distance - * - * @author aaron - * @param int dist - */ - public void setDist(int dist){ - this.dist = dist; - } - - /** - * Set current position - * - * @author aaron - * @param Point pos - */ - public void setPos(Point pos){ - this.pos = pos; - } - - /** - * Set previous vertex - * - * @author aaron - * @param Vertex prev - */ - public void setPrev(Vertex prev){ - this.prev = prev; - } - - /** - * Get the distance - * - * @author aaron - * @return int dist - */ - public int getDist(){ - return this.dist; - } - - /** - * Get current position - * - * @author aaron - * @return Point pos - */ - public Point getPos(){ - return this.pos; - } - - /** - * Get previous vertex - * - * @author aaron - * @return Vertex prev - */ - public Vertex getPrev(){ - return this.prev; - } - -}