• 一时兴起,写了个寻路代码


    看到一个面试题,是有关寻路的,于是想练练手,自己也写一个。

    把地图坐标设计为二维数据,坐标点的值代表不同意义。

    先上代码:

      1 import java.util.ArrayList;
      2 import java.util.Collections;
      3 import java.util.Comparator;
      4 import java.util.List;
      5 
      6 public class FindLine {
      7     // 测试数据,0代表可通的路,1代表墙,5代表起点或终点
      8     public static int[][] map = { 
      9             { 0, 0, 0, 0, 0, 0 }, 
     10             { 0, 1, 0, 1, 0, 0 },
     11             { 0, 0, 5, 0, 1, 0 },
     12             { 0, 0, 0, 1, 0, 0 },
     13             { 0, 1, 1, 5, 0, 1 },
     14             { 0, 0, 1, 0, 0, 0 } };
     15 
     16     // 方向 = 0,1,2,3 上右下左
     17     public static int[][] move = { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 } }; // 上,右,下,左
     18     // 记录已经查询过路径
     19     public static int[][] used = { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0 },
     20             { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0 },
     21             { 0, 0, 0, 0, 0, 0 } };
     22 
     23     /**
     24      * @author Huang
     25      * @return void
     26      */
     27 
     28     public static void main(String[] args) {
     29 
     30         int[] o1 = { 2, 2 }; // 起点
     31         int[] o2 = { 4, 3 }; // 终点
     32         if (eq(o1, o2)) {
     33             used[o1[0]][o1[1]] = 1;
     34             runLineOld.add(o1);
     35             if (count(o1, o2)) {
     36                 used[o2[0]][o2[1]] = 1;
     37                 runLineOld.add(o2);
     38                 reline();
     39                 System.out.println();
     40                 System.out.println("寻路记录的点(用2来表示)");
     41                 for (int i = 0; i < used.length; i++) {
     42                     for (int j = 0; j < used[i].length; j++) {
     43                         System.out.print(used[i][j] + "  ");
     44                     }
     45                     System.out.println();
     46                 }
     47                 
     48                 System.out.println("初始路径");
     49                 for (int[] r : runLineOld) {
     50                     System.out.print("[" + r[0] + "," + r[1] + "],");
     51                 }
     52                 System.out.println();
     53                 System.out.println("优化后路径");
     54                 for (int[] r : runLineNew) {
     55                     System.out.print("[" + r[0] + "," + r[1] + "],");
     56                 }
     57                 
     58                 
     59             }
     60         }
     61 
     62     }
     63 
     64     // 检查是否相等
     65     public static boolean eq(int[] o1, int[] o2) {
     66         return map[o1[0]][o1[1]] == map[o2[0]][o2[1]];
     67     }
     68 
     69     
     70     static List<int[]> runLineOld = new ArrayList<>(); // 初始路径
     71     static List<int[]> runLineNew = new ArrayList<>(); // 优化路径
     72 
     73     // 计算路径
     74     public static boolean count(int[] o1, int[] o2) {
     75         if (isNear(o1, o2)) {
     76             System.out.print("[" + o2[0] + "," + o2[1] + "],");
     77             return true; // yes
     78         }
     79 
     80         int[] line = findLine(o1);
     81         if (line.length == 0) {
     82             return false;// no ;
     83         }
     84 
     85         List<LineRate> lr = countRate(o1, line, o2);
     86         Collections.sort(lr, new Comparator<LineRate>() {
     87             @Override
     88             public int compare(LineRate o1, LineRate o2) {
     89                 if (o1.getR() > o2.getR()) {
     90                     return 1;
     91                 } else if (o1.getR() < o2.getR()) {
     92                     return -1;
     93                 }
     94                 return 0;
     95             }
     96         });
     97 
     98         boolean find = false;
     99         for (int i = 0; i < lr.size(); i++) {
    100             int[] ot = new int[2];
    101             ot[0] = o1[0] + move[lr.get(i).getF()][0];
    102             ot[1] = o1[1] + move[lr.get(i).getF()][1];
    103             if (used[ot[0]][ot[1]] == 1) {
    104                 continue;
    105             }
    106             used[ot[0]][ot[1]] = 1;
    107             runLineOld.add(ot);
    108             System.out.print("[" + ot[0] + "," + ot[1] + "],");
    109             if (count(ot, o2)) {
    110                 // yes
    111                 find = true;
    112                 break;
    113             } else {
    114                 used[ot[0]][ot[1]] = 2;// 此路不通
    115                 System.out.print("|");
    116                 runLineOld.remove(runLineOld.size() - 1);
    117                 continue;
    118             }
    119         }
    120         return find;
    121 
    122     }
    123 
    124     public static boolean isNear(int[] o1, int[] o2) {
    125         if (o1[0] == o2[0] && Math.abs(o1[1] - o2[1]) == 1) {
    126             return true;
    127         } else if (o1[1] == o2[1] && Math.abs(o1[0] - o2[0]) == 1) {
    128             return true;
    129         } else {
    130             return false;
    131         }
    132     }
    133 
    134     // 找出可用路径
    135     public static int[] findLine(int[] o1) {
    136 
    137         List<Integer> cl = new ArrayList<>();
    138 
    139         for (int i = 0; i < 4; i++) {
    140             if (checkUse(o1, i) == 1) {
    141                 cl.add(i);
    142             }
    143         }
    144         int[] f = new int[cl.size()];
    145         for (int i = 0; i < f.length; i++) {
    146             f[i] = cl.get(i);
    147         }
    148         return f;
    149 
    150     }
    151 
    152     // 检查该位置是否可用,1是,0否
    153     public static int checkUse(int[] o1, int f) {
    154 
    155         int xt1 = o1[0] + move[f][0];
    156         int yt1 = o1[1] + move[f][1];
    157         if (xt1 > -1 && xt1 < map[0].length && yt1 > -1 && yt1 < map.length
    158                 && used[xt1][yt1] == 0) {
    159             if (map[xt1][yt1] == 0) {
    160                 return 1;
    161             }
    162         }
    163         return 0;
    164     }
    165 
    166     // 计算权重
    167     public static List<LineRate> countRate(int[] ot, int[] f, int[] o2) {
    168 
    169         // r = g + h , g = 10 , h = |x2 - x1 |+ |y2 - y1|
    170         int g = 10;
    171         List<LineRate> list = new ArrayList<>();
    172         for (int i = 0; i < f.length; i++) {
    173             int otx = ot[0] + move[f[i]][0];
    174             int oty = ot[1] + move[f[i]][1];
    175             int r = Math.abs(o2[0] - otx) + Math.abs(o2[1] - oty) + g;
    176             LineRate lr = new LineRate();
    177             lr.setF(f[i]);
    178             lr.setR(r);
    179             list.add(lr);
    180         }
    181         return list;
    182 
    183     }
    184 
    185     // 线路与权重
    186     static class LineRate {
    187         int f;
    188         int r;
    189 
    190         public int getF() {
    191             return f;
    192         }
    193 
    194         public void setF(int f) {
    195             this.f = f;
    196         }
    197 
    198         public int getR() {
    199             return r;
    200         }
    201 
    202         public void setR(int r) {
    203             this.r = r;
    204         }
    205     }
    206 
    207     // 修正路径
    208     public static void reline() {
    209 
    210         List<Integer> record = new ArrayList<>();
    211         int len = runLineOld.size() - 1;
    212         int i = 0;
    213         int j = len;
    214         record.add(i);
    215         runLineNew.add(runLineOld.get(i));
    216         while (true) {
    217             while (i < j && !isNear(runLineOld.get(i), runLineOld.get(j))) {
    218                 j--;
    219             }
    220             if (i < j) { // 找到可优化的路径
    221                 i = j;
    222                 runLineNew.add(runLineOld.get(i));
    223                 j = len;
    224             } else if (i == len) {
    225                 break;
    226             } else if (i == j) {
    227                 i++;
    228             }
    229         }
    230     }
    231 
    232 }

    运行结果:

    [2,3],|[3,2],[3,1],[2,1],[2,0],[3,0],[4,0],[5,0],[5,1],||||[1,0],[0,0],[0,1],[0,2],[0,3],[0,4],[1,4],[1,5],[2,5],[3,5],[3,4],[4,4],[4,3],
    寻路记录的点(2寻过的路且不通,1寻找的路径,0墙)
    1  1  1  1  1  0 
    1  0  0  0  1  1 
    1  1  1  2  0  1 
    2  1  1  0  1  1 
    2  0  0  1  1  0 
    2  2  0  0  0  0 
    初始路径
    [2,2],[3,2],[3,1],[2,1],[2,0],[1,0],[0,0],[0,1],[0,2],[0,3],[0,4],[1,4],[1,5],[2,5],[3,5],[3,4],[4,4],[4,3],
    优化后路径
    [2,2],[2,1],[2,0],[1,0],[0,0],[0,1],[0,2],[0,3],[0,4],[1,4],[1,5],[2,5],[3,5],[3,4],[4,4],[4,3],

    思路:

    深度优先寻路,再采用A*算法中的权重来优先选择格子,遇到墙时,就选择权重第二小的,依此进行....

    由于是深度优先,得到的路径并不是最估的,然后再进行路径优化,得到最后的结果。

    PS:深度优先,再优化路径,这感觉在墙比较多时会高效些,广度优先,我估计不用再优化路径这步操作了,但计算量会多很多。

  • 相关阅读:
    mysql 查看数据库及表大小以及数据库扩容评估
    idea中配置mybatis 映射文件模版及 mybatis plus 自定义sql
    mybatis plus 中增删改查及Wrapper的使用
    mybatis plus 主键策略
    搭建 spring boot + mybatis plus 项目框架并进行调试
    jeecg datagrid重新指定数据源
    java 日志脱敏框架 sensitive-新版本0.0.2-深度拷贝,属性为对象和集合的
    java 实现敏感词(sensitive word)工具详解使用说明
    java 日志脱敏框架 sensitive,优雅的打印脱敏日志
    互联网公司OpenAPI链接
  • 原文地址:https://www.cnblogs.com/hellohuang/p/find_line.html
Copyright © 2020-2023  润新知