代码和测试图片下载地址:
https://download.csdn.net/download/r77683962/90089371
这个地图里黑色部分是不能通过的,白色部分是可以通过的,这个算法没问题,有点感觉效率不太高。。。。。
效果:
源代码PathFind.java(代码其实来源于网上,出处找不到了。。。不好意思)
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.logging.Logger;class Coord
{public int x;public int y;public Coord(int x, int y){this.x = x;this.y = y;}@Overridepublic boolean equals(Object obj){if (obj == null) return false;if (obj instanceof Coord){Coord c = (Coord) obj;return x == c.x && y == c.y;}return false;}
}class Node implements Comparable<Node>
{public Coord coord; // 坐标public Node parent; // 父结点public int G; // G:是个准确的值,是起点到当前结点的代价public int H; // H:是个估值,当前结点到目的结点的估计代价public Node(int x, int y){this.coord = new Coord(x, y);}public Node(Coord coord, Node parent, int g, int h){this.coord = coord;this.parent = parent;G = g;H = h;}@Overridepublic int compareTo(Node o){if (o == null) return -1;if (G + H > o.G + o.H)return 1;else if (G + H < o.G + o.H) return -1;return 0;}
}class MapInfo
{public int[][] maps; // 二维数组的地图public int width; // 地图的宽public int height; // 地图的高public Node start; // 起始结点public Node end; // 最终结点public MapInfo(int[][] maps, int width, int height, Node start, Node end){this.maps = maps;this.width = width;this.height = height;this.start = start;this.end = end;}
}public class PathFind extends JFrame {public final static int BAR = 1; // 障碍值public final static int PATH = 2; // 路径public final static int DIRECT_VALUE = 10; // 横竖移动代价public final static int OBLIQUE_VALUE = 14; // 斜移动代价Queue<Node> openList = new PriorityQueue<Node>(); // 优先队列(升序)List<Node> closeList = new ArrayList<Node>();Graphics graphics;static public BufferedImage bufferedImage;int startx;int starty ;int endx ;int endy ;// for input start and end pointint mouseinput;//for pathFindStartint step = 5;// for addNeighborNodeInOpenint increment = 5;Color drawFoundPathColor = new Color(255,0,0);Color drawLineColor = new Color(0,0,255);Color drawFindingColor = new Color(0,255,0);int size = 5;int width;int height;int[][] data;private Image buffer; // 双缓冲图像private Graphics bufferGraphics; // 双缓冲图像的绘图上下文static int neihborsCount = 0;static int neihborsCount2 = 0;//打印日志工具,可以看到打印时当前类,方法,行,比便方便,sout不能看到这些信息不太方便Logger logger = MyLogger.getLogger();PathFind(){try {//5984 x 4452bufferedImage = ImageIO.read(new File("src/Map_zoom_out_5.jpg"));} catch (IOException e) {throw new RuntimeException(e);}width = bufferedImage.getWidth();height = bufferedImage.getHeight();// 设置尺寸setSize(width, height);// 窗口居中setLocationRelativeTo(null);// 关闭事件setDefaultCloseOperation(3);// 用户不能调整窗口大小setResizable(true);// 标题setTitle("A Star");// 窗口可见setVisible(true);graphics = getGraphics();buffer = createImage(bufferedImage.getWidth(), bufferedImage.getHeight());bufferGraphics = buffer.getGraphics();data = new int[height][width];resetBuffer();//zoom();addMouseListener(new MouseListener() {@Overridepublic void mouseClicked(MouseEvent e) {logger.info(e.getX() + ", " + e.getY());if (mouseinput == 0){resetBuffer();startx = e.getX();starty = e.getY();bufferGraphics.setColor(new Color(0, 255, 0));bufferGraphics.fillRect(startx, starty, size, size);graphics.drawImage(buffer, 0, 0, width, height, null);mouseinput = 1;}else{mouseinput = 0;endx = e.getX();endy = e.getY();bufferGraphics.setColor(new Color(0, 255, 0));bufferGraphics.fillRect(startx, starty, size, size);bufferGraphics.fillRect(endx, endy, size, size);bufferGraphics.setColor(drawLineColor);bufferGraphics.drawLine(startx, starty, endx, endy);logger.info("start: " + data[starty][startx] + ", end: " + data[endy][endx]);graphics.drawImage(buffer, 0, 0, width, height, null);if (data[starty][startx] == 1 || data[endy][endx] == 1){//logger.info("data == 1");return;}for (int i = 0; i < height; i++) {StringBuilder s1 = new StringBuilder();for (int j = 0; j < width; j++) {s1.append(data[i][j]);}// logger.info(s.toString());}increment = 5;System.out.println("width: " + width + " height: " + height);// start find pathpathFindStart(new MapInfo(data, width, height, new Node(startx / step * step,starty / step * step),new Node(endx / step * step,endy / step * step)));startx = 0;starty = 0;endx = 0;endy = 0;}}@Overridepublic void mousePressed(MouseEvent e) {}@Overridepublic void mouseReleased(MouseEvent e) {}@Overridepublic void mouseEntered(MouseEvent e) {}@Overridepublic void mouseExited(MouseEvent e) {}});bufferGraphics.drawImage(bufferedImage,0,0,null);//1831 x 840//startx = 400;//starty = 400;//endx = 1400;//endy = 700;}void resetBuffer(){StringBuilder s = new StringBuilder();for (int i = 0; i < height; i++) {for (int j = 0; j < width; j++) {s = new StringBuilder();final int rgb = bufferedImage.getRGB(j, i);//logger.info(" == " + rgb);//logger.info(i + " " + j + " " + data[i][j]);if (rgb == -1) //不能走的区域{data[i][j] = 0;bufferGraphics.setColor(new Color(255, 255, 255));}else //可以走的区域{//logger.info("== -16777216");data[i][j] = 1;bufferGraphics.setColor(new Color(0, 0, 0));}bufferGraphics.drawLine(j, i, j, i);}}graphics.drawImage(buffer, 0, 0, width, height, null);}// zoom outvoid zoom(){logger.info("zoom");int zoomOutTimes = 5;BufferedImage bufferedImage1 = new BufferedImage(width / zoomOutTimes + 1, height / zoomOutTimes + 1, java.awt.image.BufferedImage.TYPE_INT_RGB);int i, j;for (i = 0; i < height / zoomOutTimes ; i++){for (j = 0; j < width / zoomOutTimes; j++){int temp = 0;for (int k = 0; k < zoomOutTimes; k++) {for (int l = 0; l < zoomOutTimes; l++) {if (i * zoomOutTimes + k > height || j * zoomOutTimes + l > width){continue;}temp += data[i * zoomOutTimes + k][j * zoomOutTimes + l];}}//logger.info(String.valueOf(temp));if (temp > 20){bufferedImage1.setRGB(j,i,0);}else{bufferedImage1.setRGB(j,i,0xffffff);}}//bufferGraphics2.drawLine(j, i, j, i);}//graphics.drawImage(buffer2, 0, 0, windowWidth, windowHeight, null);try {//5984 x 4452final boolean write = ImageIO.write(bufferedImage1, "jpg", new File("img/Map_zoom_out_" + zoomOutTimes+ ".jpg"));logger.info(String.valueOf(write));} catch (IOException e) {throw new RuntimeException(e);}logger.info("String.valueOf(write)");}@Overridepublic void repaint(long time, int x, int y, int width, int height) {super.repaint(time, x, y, width, height);graphics.drawImage(buffer, 0, 0, width, height + 200, null);}/*** 判断结点是否是最终结点*/private boolean isEndNode(Coord end,Coord coord){return coord != null && end.equals(coord);}/*** 判断结点能否放入Open列表*/private boolean canAddNodeToOpen(MapInfo mapInfo,int x, int y){// 是否在地图中if (x < 0 || x >= mapInfo.width || y < 0 || y >= mapInfo.height)return false;//logger.info("canAddNodeToOpen: " + x + ", " + y + ": " + mapInfo.maps[y][x]);// 判断是否是不可通过的结点if (mapInfo.maps[y][x] == 1) return false;// 判断结点是否存在close表if (isCoordInClose(x, y)) return false;return true;}/*** 判断坐标是否在close表中*/private boolean isCoordInClose(Coord coord){return coord!=null&&isCoordInClose(coord.x, coord.y);}/*** 判断坐标是否在close表中*/private boolean isCoordInClose(int x, int y){if (closeList.isEmpty())return false;for (Node node : closeList){if (node.coord.x == x && node.coord.y == y){return true;}}return false;}private int calcH(Coord end,Coord coord){return Math.abs(end.x - coord.x) + Math.abs(end.y - coord.y);}private Node findNodeInOpen(Coord coord){//logger.info("");if (coord == null || openList.isEmpty()) return null;for (Node node : openList){if (node.coord.equals(coord)){return node;}}return null;}/*** 添加所有邻结点到open表*/private void addNeighborNodeInOpen(MapInfo mapInfo,Node current){int x = current.coord.x;int y = current.coord.y;bufferGraphics.setColor(drawFindingColor);bufferGraphics.drawLine(x, y, x+3, y+3);//logger.info("x: " + x + " y: " + y);graphics.drawImage(buffer, 0, 0, width, height, null);//logger.info("addNeighborNodeInOpen: " + x + ", " + y + ": " + mapInfo.maps[y][x]);// 左addNeighborNodeInOpen(mapInfo,current, x - increment, y, DIRECT_VALUE);// 上addNeighborNodeInOpen(mapInfo,current, x, y - increment, DIRECT_VALUE);// 右addNeighborNodeInOpen(mapInfo,current, x + increment, y, DIRECT_VALUE);// 下addNeighborNodeInOpen(mapInfo,current, x, y + increment, DIRECT_VALUE);// 左上addNeighborNodeInOpen(mapInfo,current, x - increment, y - increment, OBLIQUE_VALUE);// 右上addNeighborNodeInOpen(mapInfo,current, x + increment, y - increment, OBLIQUE_VALUE);// 右下addNeighborNodeInOpen(mapInfo,current, x + increment, y + increment, OBLIQUE_VALUE);// 左下addNeighborNodeInOpen(mapInfo,current, x - increment, y + increment, OBLIQUE_VALUE);}/*** 添加一个邻结点到open表*/private void addNeighborNodeInOpen(MapInfo mapInfo,Node current, int x, int y, int value){neihborsCount2++;//logger.info("addNeighborNodeInOpen: " + x + ", " + y);if (canAddNodeToOpen(mapInfo, x, y)){neihborsCount++;//logger.info("neihborsCount2: " + neihborsCount2 + "neihborsCount: " + neihborsCount);Node end=mapInfo.end;Coord coord = new Coord(x, y);int G = current.G + value; // 计算邻结点的G值Node child = findNodeInOpen(coord);if (child == null){int H=calcH(end.coord,coord); // 计算H值if(isEndNode(end.coord,coord)){child=end;child.parent=current;child.G=G;child.H=H;}else{child = new Node(coord, current, G, H);}openList.add(child);}else if (child.G > G){child.G = G;child.parent = current;// 重新调整堆openList.add(child);}}// logger.info("");}private void drawFoundPath(int[][] maps, Node end){if(end==null||maps==null) return;// logger.info("总代价:" + end.G);while (end != null){Coord c = end.coord;maps[c.y][c.x] = PATH;//logger.info(end.coord.x + " " + end.coord.y);int x = c.x;int y = c.y;bufferGraphics.setColor(drawFoundPathColor);bufferGraphics.fillRect(x, y, 3, 3);graphics.drawImage(buffer, 0, 0, width, height, null);end = end.parent;}}public void pathFindStart(MapInfo mapInfo){if(mapInfo == null){return;}// cleanopenList.clear();closeList.clear();// 开始搜索openList.add(mapInfo.start);moveNodes(mapInfo);}/*** 移动当前结点*/private void moveNodes(MapInfo mapInfo){while (!openList.isEmpty()){//logger.info("while");Node current = openList.poll();closeList.add(current);addNeighborNodeInOpen(mapInfo,current);if (isCoordInClose(mapInfo.end.coord)) // bug修正{drawFoundPath(mapInfo.maps, mapInfo.end);break;}}}public static void main(String[] args) {new PathFind();}
}
MyLogger.java
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.*;/*** 可以自已定义日志打印格式,这样看起来比较方便些**/
class MyFormatter extends Formatter
{@Overridepublic String format(LogRecord arg0){//创建StringBuilder对象来存放后续需要打印的日志内容StringBuilder builder = new StringBuilder();//获取时间SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");Date now = new Date();String dateStr = simpleDateFormat.format(now);builder.append("[");builder.append(dateStr);builder.append(" ");//拼接日志级别builder.append(arg0.getLevel()).append(" ");builder.append(arg0.getSourceClassName()).append(" ");//拼接方法名builder.append(arg0.getSourceMethodName()).append(" ");StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();String line = stackTrace[8].toString();String lineNumber = line.substring(line.indexOf(":") + 1, line.length() - 1);//拼接方法名builder.append(lineNumber).append("] ");//拼接日志内容builder.append(arg0.getMessage());//日志换行builder.append("\r\n");return builder.toString();}
}public class MyLogger {static Logger logger;static {logger = Logger.getLogger(MyLogger.class.getName());logger.setUseParentHandlers(false);//如果需要将日志文件写到文件系统中,需要创建一个FileHandler对象Handler consoleHandler = new ConsoleHandler();//创建日志格式文件:本次采用自定义的FormatterconsoleHandler.setFormatter(new MyFormatter());//将FileHandler对象添加到Logger对象中logger.addHandler(consoleHandler);}public static Logger getLogger() {return logger;}public static void main(String[] args) throws SecurityException, IOException {//Logger logger = Logger.getLogger(MyLogger.class.toString());//logger.info("123");StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();System.out.println(stackTrace.length);for (StackTraceElement s: stackTrace) {System.out.println(s.toString());}/*Logger myLogger = MyLogger.getLogger();myLogger.info("1123");-----------------------------------
©著作权归作者所有:来自51CTO博客作者mob64ca12e86bd4的原创作品,请联系作者获取转载授权,否则将追究法律责任java logger打印错误行号https://blog.51cto.com/u_16213398/7623080myLogger.info("11");*/}}