算法课设之迷宫求解问题

本文介绍了使用深度优先和广度优先算法解决迷宫问题的方法。通过在迷宫周边设置虚拟墙,避免边界检查,并利用栈记录已通过位置以防止回溯,实现动态求解过程的可视化。当无法找到终点时,输出错误信息。

问题描述

迷宫问题求解

• 使用深度优先的方法解决迷宫问题

• 规定迷宫的最外围为一圈墙,给出起点和终点要求输出一条正确的路径,但不要求为最短路径

• 使用opencv实现可视化,演示一个动态求解迷宫的过程

 

1)在迷宫求解问题上,看似些许有些难度,但是其实很简单,用一种称为广度搜索的算法,将玩家选定的初始点为出发点,向四周搜索可通行的位置,算法的设计:下—>右—>上—>左—>下,根据这个一直搜索下去。直到找到终点,否则,显示错误。

  2)为了避免多次检验是否走到边沿,将迷宫周围各镶上一条取值为九的边,相当于在迷宫的周围布上一圈无法通过的墙。

  3)为了避免有的点被重复到达,应标志通过的位置,可以采取一个栈来标记已通过的位置,当进入死胡同的时候进行回溯。

  4)当无解的时候进行错误输出即可。

源码如下

public class Maze implements MouseListener {
    static Grid[][] grid;
    static MyStack path;
    static Position start;
    static Position end;
    static int WIDTH;
    static int HEIGHT;
    JTextField start1;
    JTextField end1;
    JTextField out;
    boolean isMousePressed;

    public Maze(int width, int height) {
        WIDTH = width + 2;
        HEIGHT = height + 2;
        grid = new Grid[WIDTH][HEIGHT];
        this.layout(width + 2, height + 2);
    }

    private void layout(int width, int height) {
        int sideLength = 40;
        int frameWidth = sideLength * width + 20;
        int frameHeight = sideLength * (height + 2) + 32;
        JFrame frame = new JFrame();
        frame.setTitle("Maze Solution");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setVisible(true);
        frame.setSize(frameWidth, frameHeight);
        frame.addMouseListener(this);
        frame.setLayout(null);

        int i;
        for(i = 1; i < width - 1; ++i) {
            for(int j = 1; j < height - 1; ++j) {
                grid[i][j] = new Grid();
                grid[i][j].addMouseListener(this);
                frame.add(grid[i][j]);
                grid[i][j].setBounds(sideLength * i, sideLength * j, sideLength, sideLength);
            }
        }

        for(i = 1; i < width - 1; ++i) {
            grid[0][i] = new Grid(i);
            frame.add(grid[0][i]);
            grid[0][i].setBounds(sideLength * i, 0, sideLength, sideLength);
            grid[height - 1][i] = new Grid(i);
            frame.add(grid[height - 1][i]);
            grid[height - 1][i].setBounds(sideLength * i, sideLength * (height - 1), sideLength, sideLength);
        }

        for(i = 1; i < height - 1; ++i) {
            grid[i][0] = new Grid(i);
            frame.add(grid[i][0]);
            grid[i][0].setBounds(0, sideLength * i, sideLength, sideLength);
            grid[i][width - 1] = new Grid(i);
            frame.add(grid[i][width - 1]);
            grid[i][width - 1].setBounds(sideLength * (width - 1), sideLength * i, sideLength, sideLength);
        }

        JLabel start0 = new JLabel("enter:");
        frame.add(start0);
        start0.setBounds(0, sideLength * height, 40, 40);
        this.start1 = new JTextField();
        frame.add(this.start1);
        this.start1.setBounds(40, sideLength * height, 60, 40);
        JLabel end0 = new JLabel("exit:");
        frame.add(end0);
        end0.setBounds(100, sideLength * height, 40, 40);
        this.end1 = new JTextField();
        frame.add(this.end1);
        this.end1.setBounds(140, sideLength * height, 60, 40);
        JButton mark = new JButton("mark");
        frame.add(mark);
        mark.setBounds(sideLength * width - 210, sideLength * height, 70, 40);
        mark.addActionListener(new Maze.MarkListener());
        JButton find = new JButton("find");
        frame.add(find);
        find.setBounds(sideLength * width - 140, sideLength * height, 70, 40);
        find.addActionListener(new Maze.FindListener());
        JButton retry = new JButton("retry");
        frame.add(retry);
        retry.setBounds(sideLength * width - 70, sideLength * height, 70, 40);
        retry.addActionListener(new Maze.RetryListener());
        JLabel label = new JLabel("");
        frame.add(label);
        label.setBounds(0, sideLength * (height + 1), sideLength, sideLength);
        this.out = new JTextField();
        frame.add(this.out);
        this.out.setBounds(0, sideLength * (height + 1), frameWidth - 20, 40);
    }

    private int[] intOfStr(String str) {
        int[] result = new int[2];
        int index = str.indexOf(44);
        result[0] = Integer.parseInt(str.substring(1, index));
        result[1] = Integer.parseInt(str.substring(index + 1, str.length() - 1));
        return result;
    }

    private boolean isfit(int i, int standard) {
        return i > 0 && i < standard;
    }

    private static boolean findPath() {
        path = new MyStack();
        Position[] offset = new Position[]{new Position(1, 0), new Position(0, 1), new Position(-1, 0), new Position(0, -1)};
        Position current = start;
        grid[current.x][current.y].isWall = true;
        int option = 0;
        int lastOption = 3;
        float red = 0.0F;
        float green = 1.0F - red;

        while(current.x != end.x || current.y != end.y) {
            int gridX = 0;

            int gridY;
            for(gridY = 0; option <= lastOption; ++option) {
                gridX = current.x + offset[option].x;
                gridY = current.y + offset[option].y;
                if (!grid[gridX][gridY].isWall) {
                    break;
                }
            }

            if (option <= lastOption) {
                path.push(current);
                grid[current.x][current.y].setBackground(new Color(red, green, 0.0F, 1.0F));
                red += 0.035F;
                if (red >= 1.0F) {
                    red = 1.0F;
                    green = 1.0F - red;
                }

                current = new Position(gridX, gridY);
                grid[current.x][current.y].isWall = true;
                option = 0;
            } else {
                if (path.isEmpty()) {
                    return false;
                }

                Position next = path.pop();
                grid[next.x][next.y].setBackground(Color.WHITE);
                if (next.y == current.y) {
                    option = 2 + next.x - current.x;
                } else {
                    option = (3 + next.y - current.y) % 3;
                }

                current = next;
            }
        }

        return true;
    }

    public static void main(String[] args) {
        new Maze(9, 9);
    }

    public void mouseClicked(MouseEvent e) {
    }

    public void mouseEntered(MouseEvent e) {
        if (this.isMousePressed) {
            if (e.getComponent().getBackground() == Color.BLACK) {
                e.getComponent().setBackground(Color.WHITE);
            } else if (e.getComponent().getBackground() == Color.WHITE) {
                e.getComponent().setBackground(Color.BLACK);
            }
        }

    }

    public void mouseExited(MouseEvent e) {
    }

    public void mousePressed(MouseEvent e) {
        this.isMousePressed = true;
        if (e.getComponent().getBackground() == Color.BLACK) {
            e.getComponent().setBackground(Color.WHITE);
        } else if (e.getComponent().getBackground() == Color.WHITE) {
            e.getComponent().setBackground(Color.BLACK);
        }

    }

    public void mouseReleased(MouseEvent e) {
        this.isMousePressed = false;
    }

    class FindListener implements ActionListener {
        FindListener() {
        }

        public void actionPerformed(ActionEvent arg0) {
            for(int i = 1; i < Maze.WIDTH - 1; ++i) {
                for(int j = 1; j < Maze.HEIGHT - 1; ++j) {
                    if (Maze.grid[i][j].getBackground() == Color.BLACK) {
                        Maze.grid[i][j].setWall();
                    }
                }
            }

            if (!Maze.findPath()) {
                Maze.this.out.setText("i cannot find the way");
            } else {
                Maze.this.out.setText("success");
            }

        }
    }

    class MarkListener implements ActionListener {
        MarkListener() {
        }

        public void actionPerformed(ActionEvent arg0) {
            String str1 = Maze.this.start1.getText();
            String str2 = Maze.this.end1.getText();
            int startX = Maze.this.intOfStr(str1)[0];
            int startY = Maze.this.intOfStr(str1)[1];
            if (!Maze.this.isfit(startX, Maze.WIDTH - 1)) {
                Maze.this.out.setText("insert out of 课设.maze");
            } else if (!Maze.this.isfit(startY, Maze.HEIGHT - 1)) {
                Maze.this.out.setText("insert out of 课设.maze");
            } else {
                Maze.start = new Position(startX, startY);
                Maze.grid[startX][startY].isWall = false;
                Maze.grid[startX][startY].setBackground(new Color(0.0F, 1.0F, 0.0F, 1.0F));
                int endX = Maze.this.intOfStr(str2)[0];
                int endY = Maze.this.intOfStr(str2)[1];
                if (!Maze.this.isfit(endX, Maze.WIDTH - 1)) {
                    Maze.this.out.setText("insert out of 课设.maze");
                } else if (!Maze.this.isfit(endY, Maze.HEIGHT - 1)) {
                    Maze.this.out.setText("insert out of 课设.maze");
                } else {
                    Maze.end = new Position(endX, endY);
                    Maze.grid[endX][endY].isWall = false;
                    Maze.grid[endX][endY].setBackground(Color.RED);
                }
            }
        }
    }

    class RetryListener implements ActionListener {
        RetryListener() {
        }

        public void actionPerformed(ActionEvent arg0) {
            for(int i = 1; i < Maze.WIDTH - 1; ++i) {
                for(int j = 1; j < Maze.HEIGHT - 1; ++j) {
                    Maze.grid[i][j].isWall = false;
                    Maze.grid[i][j].setBackground(Color.WHITE);
                    Maze.this.start1.setText("");
                    Maze.this.end1.setText("");
                    Maze.this.out.setText("");
                }
            }

        }
    }
}
class Grid extends JButton implements ActionListener {
    private static final long serialVersionUID = 1L;
    boolean isWall;

    public Grid() {
        this.isWall = false;
        this.setBackground(Color.WHITE);
        this.addActionListener(this);
    }

    public Grid(int i) {
        Font font = new Font("Serif", 1, 12);
        this.isWall = true;
        this.setText(String.valueOf(i));
        this.setFont(font);
        this.setBackground(new Color(1.0F, 1.0F, 1.0F, 0.0F));
    }

    public void setWall() {
        this.isWall = true;
        this.setBackground(Color.BLACK);
    }

    public void actionPerformed(ActionEvent arg) {
        if (this.isWall) {
            this.isWall = false;
            this.setBackground(Color.WHITE);
        } else {
            this.isWall = true;
            this.setBackground(Color.BLACK);
        }

    }

    public void click() {
        if (this.isWall) {
            this.isWall = false;
            this.setBackground(Color.WHITE);
        } else {
            this.isWall = true;
            this.setBackground(Color.BLACK);
        }

    }
}

class MyNode {
    Position element;
    MyNode next;

    public MyNode(Position p) {
        this.element = new Position(p);
        this.next = null;
    }
}

 

class MyStack {
    protected MyNode top = null;

    public MyStack() {
    }

    public void push(Position element) {
        if (this.top == null) {
            this.top = new MyNode(element);
        } else {
            MyNode current = new MyNode(element);
            current.next = this.top;
            this.top = current;
        }

    }

    public Position pop() {
        if (this.isEmpty()) {
            throw new EmptyStackException();
        } else {
            Position p = this.top.element;
            this.top = this.top.next;
            return p;
        }
    }

    public boolean isEmpty() {
        return this.top == null;
    }
}
class Pos {
    int x;
    int y;
    boolean isWall;

    public Pos() {
        this.x = 0;
        this.y = 0;
        this.isWall = false;
    }

    public Pos(int _x, int _y) {
        this.x = _x;
        this.y = _y;
    }
}
class Position {
    int x;
    int y;

    public Position(int _x, int _y) {
        this.x = _x;
        this.y = _y;
    }

    public Position(Position p) {
        this.x = p.x;
        this.y = p.y;
    }
}
class PosQueue {
    QNode front = new QNode();
    QNode rear;

    public PosQueue() {
        this.rear = this.front;
    }

    public void EnQueue(Pos pos) {
        this.rear.pos = pos;
        this.rear = this.rear.next;
    }

    public void DeQueue() {
        this.front = this.front.next;
    }

    public boolean isEmpty() {
        return this.front == this.rear;
    }
}
class QNode {
    Pos pos = new Pos();
    QNode next = null;

    public QNode() {
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值