数据结构——迷宫问题

一.题意说明

求迷宫问题(见实验4-17)的所有路径。分别使用栈、队列、递归算法等实现(至少三种方法)。要求迷宫地图大小可自定义,障碍物可随机生成。

题意分析:用二维数组定义迷宫大小,确定迷宫方向。迷宫通路为1,不通为0,随机分配0和1,构造迷宫。分别用栈、队列、递归方法求解迷宫路径。采用链表存储迷宫内数据。

二.算法设计与分析

首先确定迷宫的大小,用二维数组构造迷宫,并且规定方向0—3代表上下左右。Path方法存放路径。随机使用0和1填充迷宫,0为不可通过点,1为可通过点。记录好起点和终点。1.栈:用栈格式存储路径,首先判断是否为终点,是就直接输出。不是就循环,判断该点是否来过,来过就退至栈顶,换个方向重来,如果退至栈空则没有符合的路径。2.队列:类似用广度优先遍历算法:当该点没有可走的路的时候,则放入队列,如遇到思路则回退,如遇到终点,则完成迷宫。否则队列空,则表明没有通路。3.递归调用:该算法递归调用自身没有路时,就抛出异常退出循环打印路径。首先判断上下左右有没有终点,进行循环调用自身。如果没有终点,则看上下左右有没有道路,设置数字5代表走过的路径,9代表无相通的路径。如果本次调用所有条件都不满足,说明该方向的道路是死路,该层递归结束返回上一层继续查找其他方向的路。在第一层递归调用中,如果上述条件都不满足。说明迷宫没有出口,则程序正常退出,不会抛出异常。

三. 源码

1)确认迷宫的大小和方向

  public class Path {

public int x, y; //存放横纵坐标

public int direction; //行走的方向,以0-3表示上下左右

public Path(int x, int y, int direction) //存放路径

{

this.x = x;

this.y = y;

this.direction = direction;

}

public Path()

{

this(0, 0, 0);

}

public boolean equals(Object obj)

{

if(super.equals(obj))

return true;

if(obj instanceof Path)

{

if(((Path)obj).x == this.x && ((Path)obj).y == this.y)

return true;

else

return false;

}

else

return false;

}

}

 public class Direction {

    private int x;

    private int y;

    public Direction(int x, int y) {

        this.x = x;

        this.y = y;

    }

    public int getX() {

        return x;

    }

    public void setX(int x) {

        this.x = x;

    }

    public int getY() {

        return y;

    }

    public void setY(int y) {

        this.y = y;

    }

}

2)

public class CreateLabyrinth {

private Stack<Path> pathstack = new Stack<Path>(); //以栈格式存储Path

public int[][] labyrinth; //以二维数组构造迷宫

public int x, y;

    public static double rate0=0.05;

    public static double rate1=0.95;

    

public CreateLabyrinth(int[][] mg)

{

this.labyrinth = mg;

this.x = mg.length;

this.y = mg[0].length;

}

public CreateLabyrinth(int x, int y)

{

CreateLaby(x, y);

}

public void CreateLaby(int x, int y)

{

this.x = x;

this.y = y;

this.labyrinth = new int[x][y];

MathRandom(x, y);

}

public void MathRandom(int x, int y)

{

for (int i = 0; i < x; i++)

for (int j = 0; j < y; j++)

//this.labyrinth[i][j] = (int) (Math.random() * 2); //随机使用0和1填充迷宫,0为不可通过点,1为可通过点

        this.labyrinth[i][j]=(int)(Prandom());

}

private int Prandom() {

double randomnumber=Math.random();

if(randomnumber>=0&&randomnumber<=rate0){

return 0;

}else

return 1;

}

public void printAll()

{

for (int i = 0; i < this.x; i++)

{

for (int j = 0; j < this.y; j++)

System.out.print(this.labyrinth[i][j]+" ");

System.out.println();

}

}

public Path pathnext(Path ph, boolean status)

{

if (!status)

ph.direction++;

Path newpath = new Path(ph.x, ph.y, 0);

if (ph.direction == 0)

newpath.y++;

if (ph.direction == 1)

newpath.x++;

if (ph.direction == 2)

newpath.y--;

if (ph.direction == 3)

newpath.x--;

if (newpath.x >= 0 && newpath.x < this.x && newpath.y >= 0 && newpath.y < this.y) {

return newpath;

}

return null;

}

public Path startpath(int x, int y, int direction)

{

Path startpath = new Path(x, y, direction);

this.labyrinth[x][y] = 1;

return startpath;

}

public Path endpath(int x, int y, int direction)

{

Path endpath = new Path(x, y, direction);

this.labyrinth[x][y] = 1;

return endpath;

}

public void move(Path startpath, Path endpath, int direction) //使用栈的算法

{

do{

if(this.labyrinth[startpath.x][startpath.y] == 3) // 判断是否为终点

{

if(startpath.x == endpath.x && startpath.y == endpath.y)

{

pathstack.push(startpath);

System.out.println("(" + startpath.x + "," + startpath.y + ")");

System.out.println("到达终点");

this.pathstack.removeAllElements();

return;

}

System.out.print("(" + startpath.x + "," + startpath.y + ")");

if(pathstack.contains(startpath)) // 判断是否来过

{

pathstack.pop(); // 来过则后退一个,换个方向重来

try 

{

startpath = pathstack.peek();

}

catch(EmptyStackException e) //如果退至栈空,则表明没有符合条件的路

{

System.out.println("\n没有找到到达终点的路");

return;

}

startpath = pathnext(startpath, false);

}

else //未来过该点,则入栈

{

pathstack.push(startpath);

startpath = pathnext(startpath, true);

}

}

else

{

try

{

startpath = pathstack.peek();

startpath = pathnext(startpath, false);

}

catch(EmptyStackException e) //如果退至栈空,则表明没有符合条件的路

{

System.out.println("\n没有找到到达终点的路");

return;

}

}

}while (!pathstack.empty());

}

3)队列

public void queuemove(Path startpath, Path endpath) //使用队列

{

x = startpath.x;

y = startpath.y;

Queue<Point> que = new LinkedList<Point>();

int step = 0, flag = 0;

que.offer(new Point(startpath.x, startpath.y));

while(!que.isEmpty())

{

if(step >= 100)

break;

Point p = que.poll();

if(p.x == endpath.x && p.y == endpath.y)

{

System.out.println("成功到达: (" + p.x + ", " + p.y + ")! 本次遍历共走了" + step + "步");

flag = 1;

break;

}

else //类BFS算法,当该点周围有可走的路径时放入队列,若遇到死胡同则回退,若过程中遇到终点,则完成迷宫,否则若队列空,则表示无通路

{

if(x + 1 < this.labyrinth.length && this.labyrinth[x + 1][y] == 1)

        {

this.labyrinth[x + 1][y] = 5;

        que.offer(new Point(x + 1, y));

        x++;

        step++;

        }

if(y + 1 < this.labyrinth[0].length && this.labyrinth[x][y + 1] == 1)

        {

this.labyrinth[x][y + 1] = 5;

        que.offer(new Point(x, y + 1));

        y++;

        step++;

        }

if(y - 1 >= 0 && this.labyrinth[x][y - 1] == 1)

         {

this.labyrinth[x][y - 1] = 5;

         que.offer(new Point(x, y - 1));

         y--;

         step++;

        }

if(x - 1 >= 0 && this.labyrinth[x - 1][y] == 1)

        {

this.labyrinth[x - 1][y] = 5;

        que.offer(new Point(x - 1, y));

        x--;

        step++;

        }

}

}

if(flag == 0)

System.out.println("没有符合的路径!");

}

4)递归调用

public void loopmove(Path startpath, Path endpath) //递归算法

{

 try

 {

 loopRun(startpath.x, startpath.y, endpath);

 System.out.println("该迷宫没有出口!!!"); //如果程序正常退出,说明迷宫没有出口

     }

 catch(IndexOutOfBoundsException exp)

 {

 System.out.println("该迷宫没有出口!!!");

 }

 catch(Exception e) //接收异常,退出循环并打印路径

 {

 System.out.println();

         System.out.println("找到出口! 路径如下(5代表路径):");

         for (int i = 0; i < this.labyrinth.length; i++)

         {

          for(int j = 0; j < this.labyrinth[0].length; j++)

          {

          System.out.print(this.labyrinth[i][j]);

                 if(j == this.labyrinth[0].length - 1)

                  System.out.println();   

                 else

                  System.out.print(" ");

          }

         }

     }

}

    public void loopRun(int x, int y, Path endpath) throws Exception //递归函数

    {

        this.labyrinth[x][y] = 5;

    

        if(x == endpath.x && y == endpath.y)

        {

            Exception exp= new Exception();

            throw exp; //当找到出口时,抛出一个异常,便于跳出递归循环

        }

        //判断上下左右有没有终点

        if(y - 1 >= 0 && x == endpath.x && y - 1 == endpath.y)

        {

         loopRun(x, y - 1, endpath);

        }

        if(x - 1 >= 0 && x - 1 == endpath.x && y == endpath.y)

        {

         loopRun(x - 1, y, endpath);

        }

        if(y + 1 < this.labyrinth[0].length && x == endpath.x && y + 1 == endpath.y)

        {

         loopRun(x, y + 1, endpath);

        }

        if(x + 1 < this.labyrinth.length && x + 1 == endpath.x && y == endpath.y)

        {

         loopRun(x + 1, y, endpath);

        }

        //如果没有终点,则看上下左右有没有道路

        if(x + 1 < this.labyrinth.length && this.labyrinth[x + 1][y] == 1)

        {

         loopRun(x + 1, y, endpath);  

        }

        if(y + 1 < this.labyrinth[0].length && this.labyrinth[x][y + 1] == 1)

        {

         loopRun(x, y + 1, endpath);

        }

        if(y - 1 >= 0 && this.labyrinth[x][y - 1] == 1)

        {

         loopRun(x, y - 1, endpath);

        }

        if(x - 1 >= 0 && this.labyrinth[x - 1][y] == 1)

        {

         loopRun(x - 1, y, endpath);  

        }

        this.labyrinth[x][y] = 9;

        

        // 再看上下左右有没有之前走过的路并返回之前走过的路

        if(x + 1 < this.labyrinth.length && this.labyrinth[x + 1][y] == 5)

        {

         loopRun(x + 1, y, endpath);

        }

        if(y + 1 < this.labyrinth[0].length && this.labyrinth[x][y + 1] == 5)

        {

         loopRun(x, y + 1, endpath);  

        }

        if(y - 1 >= 0 && this.labyrinth[x][y - 1] == 5)

        {

         loopRun(x, y - 1, endpath);  

        }

        if(x - 1 >= 0 && this.labyrinth[x + 1][y] == 5)

        {

         loopRun(x - 1, y, endpath);  

        }

    }

public static void main(String[] args)

{

        int map[][]=new int[30][30];

        CreateLabyrinth CL= new CreateLabyrinth(map);

        CL.CreateLaby(30,30);

        CL.startpath(0,0,1);

        CL.endpath(29,29,3);

        System.out.println("迷宫地图为: ");

        CL.printAll();

        Path spath = CL.startpath(0, 0, 1);

Path endpath = CL.endpath(29, 29, 3);

//CL.move(spath, endpath,0);

//CL.queuemove(spath, endpath);

CL.loopmove(spath, endpath);

}

}

  四。结果

1.随机生成的30*30的迷宫

 2.每一步走过的坐标,显示如下

3.图中“5”代表行走的路径:

 

猜你喜欢

转载自blog.csdn.net/weixin_45823684/article/details/122469826