JavaSE-基于回溯法用类+栈实现迷宫问题

目录

 

1.问题描述

2.自定义类栈

3.结点类

4.操作类

5.函数讲解

6.测试类及结果


1.问题描述

输入迷宫大小,以及路径,0表示可走路径,1表示死路,从输入矩阵的左上角起点到右下角终口(也可简单改动自定义起点和终点)找出一条能通过的路径。

如输入大小3*3,路径为

0  0  0

0  1  1

0  0  0

最终要做的是找到并将对应路径的值改写,比如说是2,用来表示找到的路径所在,如:

2  0  0

2  1  1

2  2  2

2.自定义类栈

思路:利用回溯法去做,每次进行结点探查,能走就走,路不通就返回,因此这里利用栈去做,自定义栈类如下:

栈中用一个自定义的MazeNode类型的一维数组存储结点信息,size为栈中有效元素个数,操作主要有入栈,出栈,取栈顶元素。

package com.maze;

import java.util.Arrays;
import java.util.EmptyStackException;

/**
 * Description :
 * Created by Resumebb
 * Date :2020/10/21
 */
public class MyStack {
    private MazeNode[] element;
    private int size;
    private static final int INITSIZE = 100;

    public MyStack(){
        element = new MazeNode[INITSIZE];
    }

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }

    private void ensureCapacity(){
        if(size == element.length){
            element = Arrays.copyOf(element,element.length+(element.length>>1));
        }
    }

    public void push(MazeNode mazeNode,int row, int colum){
        ensureCapacity();
        element[size++] = mazeNode;
        mazeNode.setRow(row);
        mazeNode.setColum(colum);
    }

    public void pop(){
        if(size == 0){
            return;
        }
        size--;
    }

    public MazeNode peek(){
        if(size == 0){
            throw new EmptyStackException();
        }
        return element[size-1];
    }
}

3.结点类

接下来定义结点类:

成员变量有结点的方向,东南西北四个方向,当前所在行列坐标,以及当前结点的value值。

package com.maze;

/**
 * Description :
 * Created by Resumebb
 * Date :2020/10/21
 */
public class MazeNode {
    private int value;
    public boolean way_east;
    public boolean way_west;
    public boolean way_south;
    public boolean way_north;
    private int row;
    private int colum;

    public MazeNode(int value, int row, int colum){
        this.value = value;
        this.row = row;
        this.colum = colum;
    }

    public int getRow() {
        return row;
    }

    public void setRow(int row) {
        this.row = row;
    }

    public int getColum() {
        return colum;
    }

    public void setColum(int colum) {
        this.colum = colum;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }
}

4.操作类

定义操作类,寻路操作等在此类中进行:

package com.maze;

import java.util.Scanner;
import java.util.Stack;

/**
 * Description :
 * Created by Resumebb
 * Date :2020/10/21
 */
public class Maze {
    private MazeNode[][] mazeNodes;
    private int row;
    private int colum;

    public Maze(int row, int colum) {
        this.row = row;
        this.colum = colum;
        mazeNodes = new MazeNode[row][colum];
    }

    public int getRow() {
        return row;
    }

    public void setRow(int row) {
        this.row = row;
    }

    public int getColum() {
        return colum;
    }

    public void setColum(int colum) {
        this.colum = colum;
    }

    public void goMaze(){
        initValue();
        if(mazeNodes[0][0].getValue() != 0){
            return;
        }
        initWayState();
        MyStack stack = run();
        display(stack);
    }

    public void initValue(){
        Scanner in = new Scanner(System.in);
        System.out.println("input route:");
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < colum; j++) {
                mazeNodes[i][j] = new MazeNode(in.nextInt(),i,j);
            }
        }
    }

    private void initWayState(){
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < colum; j++) {
                if(mazeNodes[i][j].getValue() == 0){
                    //东
                    if(j+1<colum && mazeNodes[i][j+1].getValue() == 0){
                        mazeNodes[i][j].way_east = true;
                    }

                    //西
                    if(j-1>=0 && mazeNodes[i][j-1].getValue() == 0){
                        mazeNodes[i][j].way_west = true;
                    }

                    //南
                    if(i+1<row && mazeNodes[i+1][j].getValue() == 0){
                        mazeNodes[i][j].way_south = true;
                    }

                    //北
                    if(i-1>=0 && mazeNodes[i-1][j].getValue() == 0){
                        mazeNodes[i][j].way_north = true;
                    }
                }
            }
        }
    }

    //0 0 0 0 1 1 0 0 0
    public MyStack run(){
        MyStack stack = new MyStack();
        int i = 0, j = 0;
        stack.push(mazeNodes[0][0]);

        while(stack.getSize()!=0){
            //东边可走
            if(j+1<colum && mazeNodes[i][j+1].getValue() == 0 && mazeNodes[i][j+1].way_west){
                stack.push(mazeNodes[i][j+1]);
                mazeNodes[i][j].way_east = false;
                mazeNodes[i][++j].way_west = false;
            }

            //南边可走
            else if(i+1<row && mazeNodes[i+1][j].getValue() == 0 && mazeNodes[i+1][j].way_north){
                stack.push(mazeNodes[i+1][j]);
                mazeNodes[i][j].way_south = false;
                mazeNodes[++i][j].way_north = false;
            }

            //西边可走
            else if(j-1>=0 && mazeNodes[i][j-1].getValue() == 0 && mazeNodes[i][j-1].way_east){
                stack.push(mazeNodes[i][j-1]);
                mazeNodes[i][j].way_west = false;
                mazeNodes[i][--j].way_east = false;
            }

            //北边可走
            else if(i-1>=0 && mazeNodes[i-1][j].getValue() == 0  && mazeNodes[i-1][j].way_south){
                stack.push(mazeNodes[i-1][j]);
                mazeNodes[i][j].way_north = false;
                mazeNodes[--i][j].way_south = false;
            }

            //四路不通出栈
            else {
                stack.pop();
                i = stack.peek().getRow();
                j = stack.peek().getColum();
            }

            if(i==row-1 && j==colum-1){
                return stack;
            }
        }
        return stack;
    }

    public void display(MyStack stack){
        int x = 0, y = 0;
        int len = stack.getSize();
        for (int i = 0; i < len; i++) {
            x = stack.peek().getRow();
            y = stack.peek().getColum();
            mazeNodes[x][y].setValue(2);
            stack.pop();
        }
        System.out.println("route:");
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < colum; j++) {
                System.out.print(mazeNodes[i][j].getValue()+" ");
            }
            System.out.println();
        }
    }
}

5.函数讲解

在该类中主要函数是initValue(); initWayState(); run(); display();

initValue函数:

该函数的作用主要用于存储路径的二维数组初始化的数据录入操作。

 

initWayState函数:

该函数的作用是用于对每个结点的方向进行初始化,如当前结点的右边是0,则将当前结点的way_east给置TRUE,如果下方也是0,则way_south给置TRUE,像这样将整个迷宫的所有结点的方向给初始化。

 

run函数:

该函数就是让孩子去闯去跳,去勇敢的倒挂金钩。

首先将起点给入栈,然后进行轮回,按照东南西北的顺时针方向去循环(因为我要靠近右下角的终点,这样搞快点),只要检测到四个方向哪个方向的下一个结点值为0,说明这条路是通的,并且它这个结点对应的反方向值为TRUE,举个例子:

0  0  0

0  1  1

0  0  0

if(j+1<colum && mazeNodes[i][j+1].getValue() == 0 && mazeNodes[i][j+1].way_west){
                stack.push(mazeNodes[i][j+1]);
                mazeNodes[i][j].way_east = false;
                mazeNodes[i][++j].way_west = false;
            }

我先把左上角第一个结点入栈,然后去遍历,该项右边结点的值为0,说明这是一条路径,然后看右边结点的西方向是否为TRUE(也可以判断当前结点的东方向是否为TRUE,但是我喜欢反着来),如果为TRUE,就相当于这条路径是能走的,那么就将当前结点入栈,然后把当前结点的东边方向和右边结点的西边方向给置FALSE,相当于过河拆桥,只能走一次,下次就不行了,桥已经炸了,判断的时候要注意边界问题。

当走到第3个结点时,发现右边没路,南边也是1,路不通,并且回去的路也给封了,此时就要将当前结点出栈,说明此路不通,开始浪子回头,并且将i,j指针指向出栈后新栈顶元素的行列坐标。

 stack.pop();
 i = stack.peek().getRow();
 j = stack.peek().getColum();

最后直到找到一条路径,将栈给返回。

 

display函数:

这个函数就是用来进行打印路径的,遍历栈中元素,获取行列坐标,将路径对应的结点值给换成2,进行打印输出。

  public void display(MyStack stack){
        int x = 0, y = 0;
        int len = stack.getSize();
        for (int i = 0; i < len; i++) {
            x = stack.peek().getRow();
            y = stack.peek().getColum();
            mazeNodes[x][y].setValue(2);
            stack.pop();
        }

        for (int i = 0; i < row; i++) {
            for (int j = 0; j < colum; j++) {
                System.out.print(mazeNodes[i][j].getValue()+" ");
            }
            System.out.println();
        }
    }

6.测试类及结果

最后一个测试类:

package com.maze;


import java.util.Scanner;

/**
 * Description :
 * Created by Resumebb
 * Date :2020/10/21
 */
public class TestDemo {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.println("input size:");
        int row = in.nextInt();
        int colum = in.nextInt();
        Maze maze = new Maze(row,colum);
        maze.goMaze();
    }
}

 

测试后结果:

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值