Java Swing实现可视化可交互的A*算法演示--重制


前言

因为某些原因重启了这个项目,就重新梳理了一边项目,并且增加了一些功能。
原项目可见链接


一、运行效果

黄色(s)是起点
粉色(e)是终点
浅蓝色(s)是寻找过的路径
深蓝色(r)是找到的路径
在这里插入图片描述
在这里插入图片描述

二、代码

1.项目目录

在这里插入图片描述

2.代码

TestGUI.java

package main;

import util.Global;
import window.Window;

/**
 * 测试类
 */
public class TestGUI {
    public static void main(String[] args) {
        Global.window = new Window();
        Global.window.init();
    }
}

Window.java

package window;

import javax.swing.*;
import java.util.Arrays;

import static javax.swing.JFrame.EXIT_ON_CLOSE;

import listener.*;
import util.*;

/**
 * ui
 */
public class Window {
    private JFrame frame;
    private JPanel panel;
    private Integer[] names;
    private State[][] data;
    private JTable table;
    private JButton changeMap;
    private JButton setStart;
    private JButton setEnd;
    private JButton setWall;
    private JButton run;
    private JButton recovery;
    private JList<String> algorithms;
    private JLabel algLabel;
    private JLabel tip;

    public boolean init() {
        //创建窗口
        frame = new JFrame("经典寻路算法演示");
        frame.setSize(800, 600);
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        //frame.setLocation(200, 200);
        frame.setLayout(null);
        frame.setResizable(false);
        //创建panel存放table
        panel = new JPanel();
        panel.setBounds(0, 0, Global.COL_WIDTH * Global.COL, Global.ROW_HEIGHT * Global.ROW);
        frame.add(panel);
        //新建table
        names = new Integer[Global.COL];
        Arrays.fill(names, 0);
        data = new State[Global.ROW][Global.COL];
        for (int i = 0; i < Global.ROW; i++) {
            for (int j = 0; j < Global.COL; j++) {
                data[i][j] = State.normal;
            }
        }
        table = new SimpleTable(data, names);

        //设置table的行高列宽
        table.setRowHeight(Global.ROW_HEIGHT);
        table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        for (int j = 0; j < table.getColumnCount(); j++) {
            table.getColumnModel().getColumn(j).setPreferredWidth(Global.COL_WIDTH);
        }
        table.addMouseListener(new TableListener());
        panel.add(table);
        //设置按钮
        changeMap = new JButton(Global.CHANGE_MAP);
        changeMap.setBounds(Global.COL_WIDTH * Global.COL + 30, Global.ROW_HEIGHT * Global.ROW_HEIGHT - 150, 140, 40);
        changeMap.addActionListener(new ButtonActionListener());
        frame.add(changeMap);
        recovery = new JButton(Global.RECOVERY);
        recovery.setBounds(Global.COL_WIDTH * Global.COL + 30, Global.ROW_HEIGHT * Global.ROW_HEIGHT - 100, 140, 40);
        recovery.addActionListener(new ButtonActionListener());
        frame.add(recovery);
        setStart = new JButton(Global.SET_STAT);
        setStart.setBounds(Global.COL_WIDTH * Global.COL + 30, Global.ROW_HEIGHT * Global.ROW_HEIGHT -50, 140, 40);
        setStart.addActionListener(new ButtonActionListener());
        frame.add(setStart);
        setEnd = new JButton(Global.SET_END);
        setEnd.setBounds(Global.COL_WIDTH * Global.COL + 30, Global.ROW_HEIGHT * Global.ROW_HEIGHT, 140, 40);
        setEnd.addActionListener(new ButtonActionListener());
        frame.add(setEnd);
        setWall = new JButton(Global.SET_WALL);
        setWall.setBounds(Global.COL_WIDTH*Global.COL+30,Global.ROW_HEIGHT*Global.ROW_HEIGHT+50,140,40);
        setWall.addActionListener(new ButtonActionListener());
        frame.add(setWall);
        run = new JButton(Global.RUN);
        run.setBounds(Global.COL_WIDTH * Global.COL + 30, Global.ROW_HEIGHT * Global.ROW_HEIGHT + 100, 140, 40);
        run.addActionListener(new RunListener());
        frame.add(run);
        //设置列表
        String[] al = new String[]{"BFS算法","DFS算法","A*算法"};
        algorithms = new JList<>(al);
        algorithms.setFixedCellHeight(40);
        algorithms.setBounds(Global.COL_WIDTH * Global.COL + 30, 20, 140, 150);
        algorithms.addListSelectionListener(new ListListener());
        frame.add(algorithms);
        //设置label
        algLabel = new JLabel("已选择BFS算法");
        algLabel.setBounds(Global.COL_WIDTH * Global.COL + 40, 170, 140, 50);
        frame.add(algLabel);
        tip = new JLabel("请设置坐标");
        tip.setBounds(Global.COL_WIDTH * Global.COL + 40, 200, 140, 50);
        frame.add(tip);
        frame.setVisible(true);
        return true;
    }

    public void setAlgoLabelText(String str) {
        algLabel.setText(str);
    }

    public void setTipText(String str) {
        tip.setText(str);
    }

    public JFrame getFrame() {
        return frame;
    }

    public void setFrame(JFrame frame) {
        this.frame = frame;
    }

    public JPanel getPanel() {
        return panel;
    }

    public void setPanel(JPanel panel) {
        this.panel = panel;
    }

    public Integer[] getNames() {
        return names;
    }

    public void setNames(Integer[] names) {
        this.names = names;
    }

    public State[][] getData() {
        return data;
    }

    public void setData(State[][] data) {
        this.data = data;
    }

    public JTable getTable() {
        return table;
    }

    public void setTable(JTable table) {
        this.table = table;
    }

    public JButton getSetStart() {
        return setStart;
    }

    public void setSetStart(JButton setStart) {
        this.setStart = setStart;
    }

    public JButton getRun() {
        return run;
    }

    public void setRun(JButton run) {
        this.run = run;
    }

    public JList<String> getAlgorithms() {
        return algorithms;
    }

    public void setAlgorithms(JList<String> algorithms) {
        this.algorithms = algorithms;
    }

    public JLabel getAlgLabel() {
        return algLabel;
    }

    public void setAlgLabel(JLabel algLabel) {
        this.algLabel = algLabel;
    }
}

Global.java

package util;

import window.Window;

/**
 * 一些全局变量
 */
public class Global {
    public static Window window;
    public static final int ROW = 30;
    public static final int COL = 30;
    public static final int ROW_HEIGHT = 20;
    public static final int COL_WIDTH = 20;
    public static final String SET_STAT = "设置起点";
    public static final String SET_END = "设置终点";
    public static final String SET_WALL = "设置障碍";
    public static final String CHANGE_MAP = "换地图";
    public static final String RECOVERY = "复位";
    public static final String RUN = "Run";
    public static final String DFS = "DFS算法";
    public static final String BFS = "BFS算法";
    public static final String A = "A*算法";
    public static Action action = Action.normal;
    public static Algorithm algorithm = Algorithm.BFS;

    public static int startNum = 0;
    public static int endNum = 0;
    public static int startRow = 0;
    public static int startCol = 0;

    public static int endRow = 0;
    public static int endCol = 0;
    public static Thread draw = null;

}

State.java

package util;

/**
 * 表格单元格中的值(状态)
 */
public enum State {
    normal,
    start,
    end,
    wall,
    road,
    search
}

Action.java

package util;

/**
 * 当前操作状态
 *
 * @author: lsxuan
 * @email: 1146887979@qq.com
 * @create: 2022-10-09 18:44
 */
public enum Action {
    normal,
    setSta,
    setEnd,
    setWall,
    Recovery,
}

Algorithm.java

package util;

/**
 * 选择的算法
 *
 * @author: lsxuan
 * @email: 1146887979@qq.com
 * @create: 2022-10-09 18:44
 */
public enum Algorithm {
    DFS,//深度优先
    BFS,//广度优先
    A
}

SimpleTable.java

package util;

import javax.swing.*;
import java.awt.*;

/**
 * 自定义表格样式
 * 为了使单元格不能通过点击编辑
 * 以及通过单元格的值渲染颜色
 */
public class SimpleTable extends JTable {
    Color color = getForeground();

    public SimpleTable(Object[][] rowData, Object[] columnNames) {
        super(rowData, columnNames);
    }

    //设置table中值不可编辑
    public boolean isCellEditable(int row, int col) {
        return false;
    }

    @Override
    public java.awt.Component prepareRenderer(javax.swing.table.TableCellRenderer renderer, int row, int column) {
        int modelRow = convertRowIndexToModel(row);
        int modelColumn = convertColumnIndexToModel(column);
        java.awt.Component comp = super.prepareRenderer(renderer, row, column);
        if (!isRowSelected(modelRow)) {
            switch ((State) Global.window.getTable().getValueAt(modelRow, modelColumn)) {
                case start:
                    comp.setBackground(Color.orange);
                    break;
                case end:
                    comp.setBackground(Color.magenta);
                    break;
                case road:
                    comp.setBackground(Color.BLUE);
                    break;
                case search:
                    comp.setBackground(Color.cyan);
                    break;
                case wall:
                    comp.setBackground(Color.BLACK);
                    break;
                default:
                    comp.setBackground(Color.WHITE);
            }
        }
        return comp;
    }
}

Maze.java

package util.maze;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Stack;

/**
 * Maze
 *
 * 这部分借鉴了一个网上的代码,但是当时忘记留下链接了,现在找不到了。。。
 */
public class Maze {
    private int len = 11; //迷宫长度
    private int wid = 11; //迷宫宽度
    private char wall = '■'; //代表墙
    private char blank = '○'; //代表空地
    private char[][] maze; //迷宫
    private boolean[][] visit; //用来标记某一格是否被访问过
    private Node start = new Node(0, 0); //开始节点
    private Node exit = new Node(len - 1, wid - 1); //出口,其实现在也没什么用,因为没有交互只是生成了一个迷宫而已
    private Node cur; //当前格
    private Node next; //下
    private Stack path = new Stack(); //表示路径的栈
    private int[][] adj = {

            {0, 2}, {0, -2}, {2, 0}, {-2, 0}

    }; //用来计算邻接格

    /**
     * 迷宫的格子类
     *
     * @author Yan
     */

    class Node {

        int x, y;

        public Node() {
        }

        public Node(int x, int y) {
            this.x = x;
            this.y = y;
        }
        public String toString() {
            return "Node [x=" + x + ", y=" + y + "]";
        }

    }

    /**
     * 初始化,初始化迷宫参数
     */

    public void init() {
        maze = new char[len][wid];
        visit = new boolean[len][wid];
        for (int i = 0; i < len; i++) {
            for (int j = 0; j < wid; j++) {
                maze[i][j] = wall;
                visit[i][j] = false;
            }
        }
        visit[start.x][start.y] = true;
        maze[start.x][start.y] = blank;
        cur = start; //将当前格标记为开始格
    }

    /**
     * 打印结果
     */

    public void printMaze() {
        for (int i = 0; i < len; i++) {
            for (int j = 0; j < wid; j++) {

                System.out.print(maze[i][j] + " ");
            }
            System.out.println();
        }
        System.out.println("==========================================");
    }

    /**
     * 开始制作迷宫
     */

    public void makeMaze() {
        path.push(cur); //将当前格压入栈
        while (!path.empty()) {
            Node[] adjs = notVisitedAdj(cur);//寻找未被访问的邻接格
            if (adjs.length == 0) {
                cur = (Node) path.pop();//如果该格子没有可访问的邻接格,则跳回上一个格子
                continue;
            }
            next = adjs[new Random().nextInt(adjs.length)]; //随机选取一个邻接格
            int x = next.x;
            int y = next.y;
            //如果该节点被访问过,则回到上一步继续寻找
            if (visit[x][y]) {
                cur = (Node) path.pop();
            } else//否则将当前格压入栈,标记当前格为已访问,并且在迷宫地图上移除障碍物
            {
                path.push(next);
                visit[x][y] = true;
                maze[x][y] = blank;
                maze[(cur.x + x) / 2][(cur.y + y) / 2] = blank; //移除当前格与下一个之间的墙
                cur = next;//当前格等于下一格
            }
        }
    }

    /**
     * 判断节点是否都被访问
     *
     * @param ns
     * @return
     */
    public boolean allVisited(Node[] ns) {
        for (Node n : ns) {
            if (!visit[n.x][n.y])
                return false;
        }
        return true;
    }

    /**
     * 寻找可访问的邻接格,这里可以优化,不用list
     *
     * @param node
     * @return
     */
    public Node[] notVisitedAdj(Node node) {
        List list = new ArrayList();
        for (int i = 0; i < adj.length; i++) {
            int x = node.x + adj[i][0];
            int y = node.y + adj[i][1];
            if (x >= 0 && x < len && y >= 0 && y < wid) {
                if (!visit[x][y])
                    list.add(new Node(x, y));
            }
        }
        Node[] a = new Node[list.size()];
        for (int i = 0; i < list.size(); i++) {
            a[i] = (Node) list.get(i);
        }
        return a;
    }

    public int getLen() {
        return len;
    }

    public void setLen(int len) {
        this.len = len;
    }

    public int getWid() {
        return wid;
    }

    public void setWid(int wid) {
        this.wid = wid;
    }

    public char[][] getMaze() {
        return maze;
    }

    /**
     * 入口方法
     *
     * @param args
     */
    public static void main(String[] args) {
        Maze m = new Maze();
        m.init();
        m.makeMaze();
        m.printMaze();
    }
}

MazeUtil.java

package util.maze;

import util.Global;

/**
 * TODO
 *
 * @author: lsxuan
 * @email: 1146887979@qq.com
 * @create: 2022-10-09 22:21
 */
public class MazeUtil {
    public static int[][] getMap(){
        int raw = Global.ROW;
        int col = Global.COL;
        Maze maze = new Maze();
        maze.setLen(raw-3);
        maze.setWid(col-1);
        maze.init();
        maze.makeMaze();
        //maze.printMaze();
        char[][] mazeContent = maze.getMaze();
        int[][] result = new int[30][30];
        for (int i = 0; i < raw; i++) {
            for (int j = 0; j < col; j++) {
                if(j==0||j==raw-1||i==0||i==col-1||i==col-2||i==col-3){
                    result[i][j]=1;
                } else if (mazeContent[i-1][j-1]=='■') {
                    result[i][j]=1;
                }else if (mazeContent[i-1][j-1]=='○'){
                    result[i][j]=0;
                }

            }
        }
        return result;
    }

    public static void main(String[] args) {
        int[][] re = getMap();
        for (int i = 0; i < 30; i++) {
            for (int j = 0; j < 30; j++) {
                System.out.print(re[i][j]+" ");
            }
            System.out.print("\n");
        }
    }
}

Algorithm.java

package algorithm;


import util.Global;
import util.State;

import java.util.List;
import java.util.Set;

/**
 * 算法父类
 *
 * @author: lsxuan
 * @email: 1146887979@qq.com
 * @create: 2022-10-09 18:48
 */
public abstract class Algorithm {
    /**
     * 计算路径
     * @param startRow
     * @param startCol
     * @param endRow
     * @param endCol
     * @return
     */
    abstract public List<Point> compute(int startRow, int startCol, int endRow, int endCol);

    /**
     * 在ui上渲染路径
     * @param road
     */
    public static void drawRoad(List<Point> road) {
        try {
            for (int i = 1; i < road.size() - 1; i++) {
                State state = (State) Global.window.getTable().getValueAt(road.get(i).row, road.get(i).col);
                if (state == State.normal){
                    Global.window.getTable().setValueAt(State.search, road.get(i).row, road.get(i).col);
                    Thread.sleep(300);
                }
            }

            Thread.sleep(1000);
        } catch (InterruptedException e) {
        }


        Point p = road.get(road.size() - 1);
        while (p.parent != null) {
            p = p.parent;
            State state = (State) Global.window.getTable().getValueAt(p.row, p.col);
            if (state == State.normal || state == State.search)
                Global.window.getTable().setValueAt(State.road, p.row, p.col);
        }


    }

    /**
     * 判断一个点是否能走
     * @param row
     * @param col
     * @return
     */
    public static boolean isWalkable(int row, int col) {
        if (row < 1 || row > Global.ROW - 2 || col < 1 || col > Global.COL - 2) return false;
        if (Global.window.getTable().getValueAt(row, col) == State.wall) return false;
        return true;
    }

    /**
     * 获取所有邻接的点(能走的)
     * @param point
     * @return
     */
    public abstract Set<Point> getAdjacentPoints(Point point);
}

Point.java

package algorithm;

/**
 * 表示一个点
 *
 * @author: lsxuan
 * @email: 1146887979@qq.com
 * @create: 2022-10-09 18:49
 */
public class Point {
    //坐标
    public int row;
    public int col;
    //路径上的前序结点
    public Point parent;
    //A*算法中的代价
    public int F;
    public int G;
    public int H;

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("(").append(row).append(",").append(col).append(")->(").append(parent == null ? "null" : parent.row)
                .append(",").append(parent == null ? "null" : parent.col).append(")").append(F).append(",").append(G)
                .append(",").append(H);
        return sb.toString();
    }

    public Point(int row, int col, int G, int H, Point parent) {
        this.row = row;
        this.col = col;
        this.G = G;
        this.H = H;
        this.F = G + H;
        this.parent = parent;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Point point = (Point) o;
        return row == point.row && col == point.col;
    }

}

BFS.java

package algorithm;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * BFS算法
 *
 * @author: lsxuan
 * @email: 1146887979@qq.com
 * @create: 2022-10-09 18:51
 */
public class BFS extends Algorithm {
    @Override
    public List<Point> compute(int startRow, int startCol, int endRow, int endCol) {
        //(1)把初始节点S0放入Open表, 建立一个CLOSED表,置为空;
        //(2)检查Open表是否为空表,若为空,则问题无解,失败退出;
        //(3)把Open表的第一个节点取出放入Closed表,并记该节点为n;
        //(4)考察节点n是否为目标节点,若是则得到问题的解成功退出;
        //(5)若节点n不可扩展,则转第(2)步;
        //(6)扩展节点n, 将其子节点放入Open表的尾部,并为每个子节点设置指向父节点的指针, 转向第(2)步。
        Point end = null;
        List<Point> close = new ArrayList<Point>();
        List<Point> open = new ArrayList<Point>();
        Point start = new Point(startRow, startCol, 0, 10 * (Math.abs(startCol - endCol) + Math.abs(startRow - endRow)), null);
        open.add(start);
        while (!open.isEmpty()) {
            Point min = open.get(0);
            close.add(min);
            System.out.println(min);
            //util.Global.window.getTable().setValueAt(util.State.road,min.row,min.col);
            open.remove(0);
            Set<Point> adjacentPoints = getAdjacentPoints(min);
            for (Point po :adjacentPoints) {
                if(close.contains(po))continue;
                boolean flag = false;
                for (Point temp1 :
                        open) {
                    if (temp1.equals(po)) {
                        flag = true;
                    }
                }
                if (!flag ) {
                    open.add(po);
                }
            }
            end = null;
            for (Point temp :
                    open) {
                if (temp.row == endRow && temp.col == endCol) {
                    end = temp;
                }
            }
            if (end != null) {
                close.add(end);
                break;
            }
        }
        if(close.get(close.size()-1).col!=endCol||close.get(close.size()-1).row!=endRow){
            close=null;
        }
        return close;
    }

    @Override
    public Set<Point> getAdjacentPoints(Point point) {
        Set<Point> result = new HashSet<>();
        if (isWalkable(point.row + 1, point.col + 1))
            result.add(new Point(point.row + 1, point.col + 1,0,0,point));
        if (isWalkable(point.row + 1, point.col))
            result.add(new Point(point.row + 1, point.col, 0,0,point));
        if (isWalkable(point.row + 1, point.col - 1))
            result.add(new Point(point.row + 1, point.col - 1, 0,0,point));
        if (isWalkable(point.row, point.col + 1))
            result.add(new Point(point.row, point.col + 1, 0,0,point));
        if (isWalkable(point.row, point.col - 1))
            result.add(new Point(point.row, point.col - 1, 0,0,point));
        if (isWalkable(point.row - 1, point.col + 1))
            result.add(new Point(point.row - 1, point.col + 1, 0,0,point));
        if (isWalkable(point.row - 1, point.col))
            result.add(new Point(point.row - 1, point.col, 0,0,point));
        if (isWalkable(point.row - 1, point.col - 1))
            result.add(new Point(point.row - 1, point.col - 1, 0,0,point));
        return result;
    }
}

DFS.java

package algorithm;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * DFS算法
 *
 * @author: lsxuan
 * @email: 1146887979@qq.com
 * @create: 2022-10-09 18:50
 */
public class DFS extends Algorithm {
    @Override
    public List<Point> compute(int startRow, int startCol, int endRow, int endCol) {
        //(1)把初始节点S0放入Open表, 建立一个CLOSED表,置为空;
        //(2)检查Open表是否为空表,若为空,则问题无解,失败退出;
        //(3)把Open表的最后一个节点取出放入Closed表,并记该节点为n;
        //(4)考察节点n是否为目标节点,若是则得到问题的解成功退出;
        //(5)若节点n不可扩展,则转第(2)步;
        //(6)扩展节点n, 将其子节点放入Open表的首部,并为每个子节点设置指向父节点的指针, 转向第(2)步。
        Point end = null;
        List<Point> close = new ArrayList<Point>();
        List<Point> open = new ArrayList<Point>();
        Point start = new Point(startRow, startCol, 0, 10 * (Math.abs(startCol - endCol) + Math.abs(startRow - endRow)), null);
        open.add(start);
        while (!open.isEmpty()) {
            Point min = open.get(open.size()-1);
            close.add(min);
            System.out.println(min);
            //util.Global.window.getTable().setValueAt(util.State.road,min.row,min.col);
            open.remove(open.size()-1);
            Set<Point> adjacentPoints = getAdjacentPoints(min);
            for (Point po :adjacentPoints) {
                if(close.contains(po))continue;
                boolean flag = false;
                for (Point temp1 :
                        open) {
                    if (temp1.equals(po)) {
                        flag = true;
                    }
                }
                if (!flag ) {
                    open.add(po);
                }
            }

            end = null;
            for (Point temp :
                    open) {
                if (temp.row == endRow && temp.col == endCol) {
                    end = temp;
                }
            }
            if (end != null) {
                close.add(end);
                break;
            }
        }
        if(close.get(close.size()-1).col!=endCol||close.get(close.size()-1).row!=endRow){
            close=null;
        }
        return close;
    }

    @Override
    public Set<Point> getAdjacentPoints(Point point) {
        Set<Point> result = new HashSet<>();
        if (isWalkable(point.row + 1, point.col + 1))
            result.add(new Point(point.row + 1, point.col + 1,0,0,point));
        if (isWalkable(point.row + 1, point.col))
            result.add(new Point(point.row + 1, point.col, 0,0,point));
        if (isWalkable(point.row + 1, point.col - 1))
            result.add(new Point(point.row + 1, point.col - 1, 0,0,point));
        if (isWalkable(point.row, point.col + 1))
            result.add(new Point(point.row, point.col + 1, 0,0,point));
        if (isWalkable(point.row, point.col - 1))
            result.add(new Point(point.row, point.col - 1, 0,0,point));
        if (isWalkable(point.row - 1, point.col + 1))
            result.add(new Point(point.row - 1, point.col + 1, 0,0,point));
        if (isWalkable(point.row - 1, point.col))
            result.add(new Point(point.row - 1, point.col, 0,0,point));
        if (isWalkable(point.row - 1, point.col - 1))
            result.add(new Point(point.row - 1, point.col - 1, 0,0,point));
        return result;
    }
}

A.java

package algorithm;

import java.util.*;

/**
 * A*算法
 *
 * @author: lsxuan
 * @email: 1146887979@qq.com
 * @create: 2022-10-09 18:49
 */
public class A extends Algorithm {

    @Override
    public List<Point> compute(int startRow, int startCol, int endRow, int endCol) {
        //int startRow,startCol,endRow,endCol;
        Point end = null;
        List<Point> close = new ArrayList<Point>();
        List<Point> open = new ArrayList<Point>();
        Point start = new Point(startRow, startCol, 0, 10 * (Math.abs(startCol - endCol) + Math.abs(startRow - endRow)), null);
        open.add(start);
        while (!open.isEmpty()) {
            Point min = open.get(0);
            close.add(min);
            System.out.println(min);
            //util.Global.window.getTable().setValueAt(util.State.road,min.row,min.col);
            open.remove(0);
            Set<Point> adjacentPoints = getAdjacentPoints(min, endRow, endCol);
            for (Point temp :
                    adjacentPoints) {
                if (close.contains(temp)) continue;

                boolean flag = false;
                Point temp2 = null;
                for (Point temp1 :
                        open) {
                    if (temp1.equals(temp)) {
                        flag = true;
                        temp2 = temp1;
                    }
                }
                if (flag && temp2 != null) {
                    if (temp.G < temp2.G) {
                        open.remove(temp2);
                        open.add(temp);

                    }
                } else {
                    open.add(temp);
                }
            }

            Collections.sort(open, new Comparator<Point>() {
                @Override
                public int compare(Point o1, Point o2) {
                    return Integer.compare(o1.F, o2.F);
                }
            });
            end = null;
            for (Point temp :
                    open) {
                if (temp.row == endRow && temp.col == endCol) {
                    end = temp;
                }
            }
            if (end != null) {
                close.add(end);
                break;
            }
        }
        if(close.get(close.size()-1).col!=endCol||close.get(close.size()-1).row!=endRow){
            close=null;
        }
        return close;
    }

    @Override
    public Set<Point> getAdjacentPoints(Point point) {
        return null;
    }

    public Set<Point> getAdjacentPoints(Point point, int endRow, int endCol) {
        Set<Point> result = new HashSet<>();
        if (isWalkable(point.row + 1, point.col + 1))
            result.add(new Point(point.row + 1, point.col + 1, point.G + 14, 10 * (Math.abs(point.row + 1 - endRow) + Math.abs(point.col + 1 - endCol)), point));
        if (isWalkable(point.row + 1, point.col))
            result.add(new Point(point.row + 1, point.col, point.G + 10, 10 * (Math.abs(point.row + 1 - endRow) + Math.abs(point.col - endCol)), point));
        if (isWalkable(point.row + 1, point.col - 1))
            result.add(new Point(point.row + 1, point.col - 1, point.G + 14, 10 * (Math.abs(point.row + 1 - endRow) + Math.abs(point.col - 1 - endCol)), point));
        if (isWalkable(point.row, point.col + 1))
            result.add(new Point(point.row, point.col + 1, point.G + 10, 10 * (Math.abs(point.row - endRow) + Math.abs(point.col + 1 - endCol)), point));
        if (isWalkable(point.row, point.col - 1))
            result.add(new Point(point.row, point.col - 1, point.G + 10, 10 * (Math.abs(point.row - endRow) + Math.abs(point.col - 1 - endCol)), point));
        if (isWalkable(point.row - 1, point.col + 1))
            result.add(new Point(point.row - 1, point.col + 1, point.G + 14, 10 * (Math.abs(point.row - 1 - endRow) + Math.abs(point.col + 1 - endCol)), point));
        if (isWalkable(point.row - 1, point.col))
            result.add(new Point(point.row - 1, point.col, point.G + 10, 10 * (Math.abs(point.row + 1 - endRow) + Math.abs(point.col - endCol)), point));
        if (isWalkable(point.row - 1, point.col - 1))
            result.add(new Point(point.row - 1, point.col - 1, point.G + 14, 10 * (Math.abs(point.row - 1 - endRow) + Math.abs(point.col - 1 - endCol)), point));
        return result;
    }
}

ButtonActionListener.java

package listener;

import util.Action;
import util.Global;
import util.State;
import util.maze.MazeUtil;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * 按钮按压事件监听
 */
public class ButtonActionListener implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {
        //System.out.println(e.getActionCommand());
        JTable table = Global.window.getTable();
        String cmd = e.getActionCommand();
        switch (cmd) {
            case Global.SET_STAT:
                Global.action = Action.setSta;
                Global.window.setTipText("设置开始位置坐标");
                break;
            case Global.SET_END:
                Global.action = Action.setEnd;
                Global.window.setTipText("设置结束位置坐标");
                break;
            case Global.RECOVERY:
                if (Global.draw != null) Global.draw.interrupt();
                Global.action = Action.normal;
                Global.startNum = 0;
                Global.endNum = 0;
                for (int i = 0; i < Global.ROW; i++) {
                    for (int j = 0; j < Global.COL; j++) {
                        table.setValueAt(State.normal, i, j);
                    }
                }
                Global.window.setTipText("恢复地图");
                break;
            case Global.SET_WALL:
                Global.action = Action.setWall;
                Global.window.setTipText("设置障碍");
                break;
            case Global.CHANGE_MAP:
                if (Global.draw != null) Global.draw.interrupt();
                Global.action = Action.normal;
                Global.startNum = 0;
                Global.endNum = 0;

                int[][] map = MazeUtil.getMap();
                for (int i = 0; i < Global.ROW; i++) {
                    for (int j = 0; j < Global.COL; j++) {
                        if (map[i][j] == 0) table.setValueAt(State.normal, i, j);
                        else table.setValueAt(State.wall, i, j);
                    }
                }
                Global.window.setTipText("随机生成地图");
                break;

        }
        System.out.println(Global.action);
    }
}

ListListener.java

package listener;

import util.Algorithm;
import util.Global;

import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

/**
 * ui右上角算法列表点击时间监听
 */

public class ListListener implements ListSelectionListener {
    @Override
    public void valueChanged(ListSelectionEvent e) {
        //System.out.println(
        String cmd = Global.window.getAlgorithms().getSelectedValue();
        System.out.println(cmd);
        switch (cmd) {
            case Global.DFS:
                Global.algorithm = Algorithm.DFS;
                Global.window.getAlgLabel().setText("已选择DFS算法");
                break;
            case Global.BFS:
                Global.algorithm = Algorithm.BFS;
                Global.window.getAlgLabel().setText("已选择BFS算法");
                break;
            case Global.A:
                Global.algorithm = Algorithm.A;
                Global.window.getAlgLabel().setText("已选择A*算法");
                break;
        }
    }
}

RunListener.java

package listener;

import algorithm.A;
import algorithm.BFS;
import algorithm.DFS;
import algorithm.Point;
import algorithm.Algorithm;
import util.Action;
import util.Global;
import util.State;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;

/**
 * run按钮的点击时间监听
 */
public class RunListener implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {
        Global.window.setTipText("开始运行");
        JTable table = Global.window.getTable();
        for (int i = 0; i < Global.ROW; i++) {
            for (int j = 0; j < Global.COL; j++) {
                if(table.getValueAt(i, j) == State.road||table.getValueAt(i, j) == State.search)table.setValueAt(State.normal, i, j);
            }
        }
        if (!(Global.endNum == 1 && Global.startNum == 1)) return;
        Global.action = Action.normal;
        Algorithm run = null;
        switch (Global.algorithm) {
            case DFS:
                run = new DFS();
                break;
            case BFS:
                run = new BFS();
                break;
            case A:
                run = new A();
                break;
        }
        List<Point> road = run.compute(Global.startRow, Global.startCol, Global.endRow, Global.endCol);
        if(road==null){
            Global.window.setTipText("此题无解");
            return;
        }
        System.out.println(road);
        Global.draw = new Thread(new java.lang.Runnable() {
            @Override
            public void run() {
                //Global.window.setTipText("猴子向箱子寻找");
                Algorithm.drawRoad(road);
            }
        });

        Global.draw.start();

    }
}

TableListener.java

package listener;

import util.Global;
import util.State;

import javax.swing.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

/**
 * ui上表格的点击事件监听
 */
public class TableListener implements MouseListener {


    @Override
    public void mouseClicked(MouseEvent e) {
        int col = Global.window.getTable().getSelectedColumn();
        int row = Global.window.getTable().getSelectedRow();
        //System.out.println("("+x+","+y+")");
        JTable table = Global.window.getTable();
        switch (Global.action) {
            case setSta:
                if (table.getValueAt(row, col) == State.start) {
                    Global.startNum = 0;
                    table.setValueAt(State.normal, row, col);
                    break;
                }
                if (Global.startNum == 0&&table.getValueAt(row, col) == State.normal) {
                    if (table.getValueAt(row, col) == State.end) {
                        Global.endNum = 0;
                    }
                    table.setValueAt(State.start, row, col);
                    Global.startNum++;
                    Global.startRow = row;
                    Global.startCol = col;
                    Global.window.setTipText("开始位置坐标已设置");
                }

                break;
            case setEnd:
                if (table.getValueAt(row, col) == State.end) {
                    Global.endNum = 0;
                    table.setValueAt(State.normal, row, col);
                    break;
                }
                if (Global.endNum == 0&&table.getValueAt(row, col) == State.normal) {
                    if (table.getValueAt(row, col) == State.start) {
                        Global.startNum = 0;
                    }
                    table.setValueAt(State.end, row, col);
                    Global.endNum++;
                    Global.endRow = row;
                    Global.endCol = col;
                    Global.window.setTipText("结束位置坐标已设置");
                }
                break;
            case setWall:
                if(table.getValueAt(row, col) == State.wall){
                    table.setValueAt(State.normal, row, col);
                }else {
                    table.setValueAt(State.wall,row,col);
                }
                if ( table.getValueAt(row, col) == State.start) {
                    Global.startNum = 0;
                }
                if ( table.getValueAt(row, col) == State.end) {
                    Global.endNum = 0;
                }

        }
    }

    @Override
    public void mousePressed(MouseEvent e) {


    }

    @Override
    public void mouseReleased(MouseEvent e) {

    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }
}

总结

没啥总结的,就不说了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值