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 openVerticies = new ArrayList(); // List of vertices openVerticies.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 openVerticies.add(new Vertex(Integer.MAX_VALUE, new Point(i, j))); } } } ArrayList allVerticies = new ArrayList(openVerticies); // List of vertices while(!openVerticies.isEmpty()){ // As long as there are vertices final Vertex u = findNearestVertex(openVerticies); openVerticies.remove(u); // Remove u from the set of vertices if(u.getDist()==Integer.MAX_VALUE) { continue; } 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, openVerticies); //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; } }