1. 程式人生 > >java使用棧解迷宮問題

java使用棧解迷宮問題

原始碼的github地址,可以下載到本地執行

  • 迷宮求解
  • 從當前入口出發,順某一方向前進,若則走通,則繼續走,否則沿原路退回,換一個方向繼續走,直到到達終點或者所有的可能的通路都走過為止
  • 需要一個後進先出的結構來儲存入口到當前位置的路徑,這個結構就是棧

關鍵點在於:要判斷一個位置 ,是否可通。 可通是指,可以通過,且之前沒有來過

package stack.demo;

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

/**
 * 用java提供的stack實現
 */
public class MazePathStack {

    static class Spath { //行走的單位格子
        private int x;
        private int y;
        private int di; //方向 0 1 2 3 表示右 下 左 上

        public Spath(int x, int y, int di) {
            this.x = x;
            this.y = y;
            this.di = di;
        }

        @Override
        public boolean equals(Object obj) {
            if (super.equals(obj)) {
                return true;
            }

            if (obj instanceof Spath) {

                if ((((Spath) obj).x == this.x) && (((Spath) obj).y == this.y)) {
                    return true;
                } else {
                    return false;
                }

            } else {
                return false;
            }

        }
    }

    private static int[][] mg = MazePathStack.creatMG();//初始化時候生成迷宮
    private static Stack<Spath> spathStack = new Stack();//路徑棧


    public static void main(String[] args) {
        Spath spath = new Spath(0, 1, 0); //初始座標為入口 (0,1)方向為向右
        do {
            if (isPass(spath)) { //判斷該座標能否通行

                //判斷該座標是否是終點
                if (isEnd(spath)) {
                    spathStack.push(spath);
                    System.out.println("到達終點,座標為:" + "(" + spath.x + "," + spath.y + ")");
                    System.out.println("路徑為");
                    printAll();
                    return;
                }

                //判斷該座標是否已經來過
                if (isRecord(spath)) {
                    //來過 則放棄棧中最新的座標 後退一格,換個方向重試
                    spathStack.pop();
                    spath = spathStack.peek();
                    spath = next(spath, false);//繼續下一步 換個方向
                } else {
                    //沒有來過 壓入棧中 記錄下來
                    spathStack.push(spath);
                    spath = next(spath, true); //繼續下一步 沿原來方向
                }

            } else {
                spath = spathStack.peek(); //後退一步
                spath = next(spath, false);//換個方向 繼續下一步
            }

        } while (!spathStack.empty());


    }

    private static void printAll() {
        //列印路徑
        List<Spath> spaths=new ArrayList<>();
        while(!spathStack.empty()){
            spaths.add(spathStack.pop());
        }
        for (int i = spaths.size()-1; i >=0 ; i--) {
            System.out.println("("+spaths.get(i).x+","+spaths.get(i).y+")");
        }
    }


    private static Spath next(Spath spath, boolean status) {
        if (status) {
            //繼續沿著原來方向
            return SpathNext(spath);

        } else {
            //換方向
            spath.di++;
            return SpathNext(spath);
        }
    }


    private static Spath SpathNext(Spath spath) {
        Spath spathNew = new Spath(spath.x, spath.y, 0);//生成新的路徑節點 新的節點方向需要重置
        //方向 0 1 2 3 表示右 下 左 上
        if (spath.di == 0) { //向右走
            spathNew.y++;
        }

        if (spath.di == 1) { //向下走
            spathNew.x++;
        }

        if (spath.di == 2) {//向左走
            spathNew.y--;
        }

        if (spath.di == 3) {//向上走
            spathNew.x--;
        }

        if (spathNew.x>=0&&spathNew.x<5&&spathNew.y>=0&&spathNew.y<10){
            return spathNew;
        }
        return null;
    }


    private static Boolean isEnd(Spath spath) {
        if (spath.x == 4 && spath.y == 4) {
            return Boolean.TRUE;
        } else {
            return Boolean.FALSE;
        }
    }

    private static Boolean isRecord(Spath spath) {
        return spathStack.contains(spath);
    }

    private static Boolean isPass(Spath spath) {
        if (spath==null){
            return Boolean.FALSE;
        }
        if (mg[spath.x][spath.y] == 1) {
            return Boolean.TRUE;
        } else {
            return Boolean.FALSE;
        }

    }

    public static int[][] creatMG() {
        //建立一個迷宮
        int mg[][] = new int[5][10];
        //建立正確的路徑,值為1表示可以通過
        mg[0][1] = 1;
        mg[1][1] = 1;
        mg[2][1] = 1;
        mg[2][2] = 1;
        mg[3][2] = 1;
        mg[3][3] = 1;
        mg[3][4] = 1;
        mg[4][4] = 1;

        //建立干擾路徑
        mg[0][2] = 1;
        mg[0][3] = 1;
        mg[0][4] = 1;
        mg[1][4] = 1;
        mg[1][5] = 1;
        mg[1][6] = 1;
        mg[2][6] = 1;
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 10; j++) {
                System.out.print(mg[i][j]);
            }
            System.out.println();
        }

        System.out.println();
        return mg;
    }
}

輸出如下:
0111100000
0100111000
0110001000
0011100000
0000100000
到達終點,座標為:(4,4)
路徑為
(0,1)
(1,1)
(2,1)
(2,2)
(3,2)
(3,3)
(3,4)
(4,4)

原始碼的github地址,可以下載到本地執行