#
Junjie
20 小时以前 96f987b030f4c961a985f07079ba12abd865fdb2
src/main/java/com/zy/common/utils/NavigateSolution.java
@@ -10,6 +10,8 @@
import com.zy.common.model.NavigateNode;
import com.zy.core.enums.MapNodeType;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiFunction;
/**
 * A*算法实现类
@@ -23,9 +25,9 @@
    //用来存放已经出现过的结点。
    Map<String, Integer> bestGMap = new HashMap<>();
    public List<List<NavigateNode>> getStationMap() {
    public List<List<NavigateNode>> getStationMap(int lev) {
        BasMapService basMapService = SpringUtils.getBean(BasMapService.class);
        BasMap basMap = basMapService.selectOne(new EntityWrapper<BasMap>().eq("lev", 1));
        BasMap basMap = basMapService.selectOne(new EntityWrapper<BasMap>().eq("lev", lev));
        if (basMap == null) {
            throw new CoolException("地图不存在");
        }
@@ -48,6 +50,51 @@
                    JSONObject valueObj = JSON.parseObject(map.getString("value"));
                    List<String> directionList = valueObj.getJSONArray("direction").toJavaList(String.class);
                    navigateNode.setDirectionList(directionList);
                }else {
                    navigateNode.setValue(MapNodeType.DISABLE.id);
                }
                navigateNode.setNodeType(nodeType);
                navigateNode.setNodeValue(map.getString("value"));
                navigateNodeRow.add(navigateNode);
            }
            navigateNodeList.add(navigateNodeRow);
        }
        return navigateNodeList;
    }
    public List<List<NavigateNode>> getRgvTrackMap(int lev) {
        BasMapService basMapService = SpringUtils.getBean(BasMapService.class);
        BasMap basMap = basMapService.selectOne(new EntityWrapper<BasMap>().eq("lev", lev));
        if (basMap == null) {
            throw new CoolException("地图不存在");
        }
        List<List<JSONObject>> dataList = JSON.parseObject(basMap.getData(), List.class);
        List<List<NavigateNode>> navigateNodeList = new ArrayList<>();
        for (int i = 0; i < dataList.size(); i++) {
            List<JSONObject> row = dataList.get(i);
            List<NavigateNode> navigateNodeRow = new ArrayList<>();
            for (int j = 0; j < row.size(); j++) {
                JSONObject map = row.get(j);
                NavigateNode navigateNode = new NavigateNode(i, j);
                String nodeType = map.getString("type");
                if(nodeType == null) {
                    navigateNode.setValue(MapNodeType.DISABLE.id);
                }else if(nodeType.equals("rgv")){
                    navigateNode.setValue(MapNodeType.NORMAL_PATH.id);
                    JSONObject valueObj = JSON.parseObject(map.getString("value"));
                    //RGV暂不控制行走方向,默认上下左右都可走
                    List<String> directionList = new ArrayList<>();
                    directionList.add("top");
                    directionList.add("bottom");
                    directionList.add("left");
                    directionList.add("right");
                    navigateNode.setDirectionList(directionList);
                }else {
                    navigateNode.setValue(MapNodeType.DISABLE.id);
@@ -110,6 +157,115 @@
        }
        //如果遍历完所有出现的结点都没有找到最终的结点,返回null
        return null;
    }
    public List<List<NavigateNode>> allSimplePaths(
            List<List<NavigateNode>> map,
            NavigateNode start,
            NavigateNode end,
            int maxDepth,    // 最大步数(边数). 建议:50/100/200;<=0 表示不限制(不建议)
            int maxPaths,    // 最大返回条数. 建议:100/500/2000;<=0 表示不限制(不建议)
            int maxCost      // 最大总代价(含拐点惩罚). <=0 表示不限制
    ) {
        List<List<NavigateNode>> results = new ArrayList<>();
        if (map == null || map.isEmpty() || map.get(0).isEmpty()) return results;
        if (start == null || end == null) return results;
        if (start.getValue() == MapNodeType.DISABLE.id || end.getValue() == MapNodeType.DISABLE.id) return results;
        // visited 用坐标 key,避免 NavigateNode equals/hashCode 不可靠导致重复判断失效
        Set<String> visited = new HashSet<>(map.size() * map.get(0).size() * 2);
        LinkedList<NavigateNode> path = new LinkedList<>();
        String startKey = keyOf(start);
        visited.add(startKey);
        path.add(start);
        AtomicInteger pathCount = new AtomicInteger(0);
        dfsAllSimplePaths(map, start, end,
                visited, path, results,
                0,  // depth
                0,  // cost
                maxDepth, maxPaths, maxCost,
                pathCount
        );
        return results;
    }
    /**
     * DFS + 回溯:枚举所有简单路径(路径中不允许重复节点)
     */
    private void dfsAllSimplePaths(
            List<List<NavigateNode>> map,
            NavigateNode current,
            NavigateNode end,
            Set<String> visited,
            LinkedList<NavigateNode> path,
            List<List<NavigateNode>> results,
            int depth,     // 当前步数(边数)
            int cost,      // 当前总代价(你可以认为是 g)
            int maxDepth,
            int maxPaths,
            int maxCost,
            AtomicInteger pathCount
    ) {
        // 防爆:条数限制
        if (maxPaths > 0 && pathCount.get() >= maxPaths) return;
        // 到达终点:收集路径
        if (current.getX() == end.getX() && current.getY() == end.getY()) {
            results.add(new ArrayList<>(path));
            pathCount.incrementAndGet();
            return;
        }
        // 防爆:深度限制(depth 表示已走的边数)
        if (maxDepth > 0 && depth >= maxDepth) return;
        // 扩展邻居(严格复用你自己的可行走方向规则)
        ArrayList<NavigateNode> neighbors = extend_current_node(map, current);
        if (neighbors == null || neighbors.isEmpty()) return;
        for (NavigateNode next : neighbors) {
            // 防爆:条数限制
            if (maxPaths > 0 && pathCount.get() >= maxPaths) return;
            if (next == null) continue;
            if (next.getValue() == MapNodeType.DISABLE.id) continue;
            String nk = keyOf(next);
            // 简单路径:不允许重复节点
            if (visited.contains(nk)) continue;
            // 你的代价规则:每步 1 + 拐点惩罚
            int stepCost = 1 + calcNodeExtraCost(current, next, end);
            int newCost = cost + stepCost;
            // 防爆:总代价限制
            if (maxCost > 0 && newCost > maxCost) continue;
            // 进入
            visited.add(nk);
            path.addLast(next);
            dfsAllSimplePaths(map, next, end,
                    visited, path, results,
                    depth + 1,
                    newCost,
                    maxDepth, maxPaths, maxCost,
                    pathCount
            );
            // 回溯
            path.removeLast();
            visited.remove(nk);
        }
    }
    private String keyOf(NavigateNode n) {
        return n.getX() + "_" + n.getY();
    }
    public ArrayList<NavigateNode> extend_current_node(List<List<NavigateNode>> map, NavigateNode current_node) {
@@ -184,6 +340,21 @@
        return null;
    }
    public NavigateNode findTrackSiteNoNavigateNode(List<List<NavigateNode>> map, int trackSiteNo) {
        for(int x = 0; x < map.size(); x++) {
            for(int y = 0; y < map.get(0).size(); y++) {
                NavigateNode node = map.get(x).get(y);
                if("rgv".equals(node.getNodeType())) {
                    JSONObject valueObj = JSON.parseObject(node.getNodeValue());
                    if(valueObj.getInteger("trackSiteNo") == trackSiteNo) {
                        return node;
                    }
                }
            }
        }
        return null;
    }
    //------------------A*启发函数------------------//
    //计算通过现在的结点的位置和最终结点的位置计算H值(曼哈顿法:坐标分别取差值相加)