java实现迷宫算法--转

沿着所有方向进行探测,有路径则走,没有路径则从栈中回退。

回溯法是一种不断试探且及时纠正错误的搜索方法,下面的求解过程采用回溯法。从入口出发,按某一方向向前探索,若能走通(未走过的),即某处可以到达,则到达一个新点,否则试探下一个方向;若所有的方向均没有通路,则沿原路返回前一点,换下一个方向继续试探,直到所有可能的通路都搜索到,或找到一条通路,或无路可走又返回到入口点。这里可以用一个栈来实现,每走一步,将该位置压入栈中,若该点无路可走,则出栈返回上一位置。
需要解决的四个问题:
(1)表示迷宫的数据结构
  设迷宫为m行n列,利用数组maze[m][n]来表示一个迷宫,maze[i][j]=0或1,其中0表示通路,1表示不通。迷宫该数组四边都为1,代表迷宫四周都是墙。这样就可以保证每个点都有8个方向可以试探。
  入口为(1,1),出口为(6,8)
  1,1,1,1,1,1,1,1,1,1
1,0,1,1,1,0,1,1,1,1
1,1,0,1,0,1,1,1,1,1
1,0,1,0,0,0,0,0,1,1
1,0,1,1,1,0,1,1,1,1
1,1,0,0,1,1,0,0,0,1
1,0,1,1,0,0,1,1,0,1
1,1,1,1,1,1,1,1,1,1
(2)试探方向
  迷宫中间每个点都有8个方向可以试探。其增量数组可以用一个8*2的二维数组move表述,表示对当前点而言,它周围8个点的行和列的坐标偏移量.具体值如下:
       x  y
0  1
1 1
1 0
1 -1
0 -1
-1 -1
-1 0
-1 1
在move数组中,x表示横坐标的增量,y表示纵坐标的增量。
  (3)栈中存放元素的设计
  栈中所存放的元素应该包含所到达的每点的坐标以及从该点沿哪个方向向下走的,可用一个类表示:
class Step{
int x,y,d;
public Step(int x,int y,int d) {
this.x = x;//横坐标
this.y = y;//纵坐标
this.d = d;//方向
}
}
(4)防止重复到达某点而发生死循环
  使maze[i][j]置为-1,以便区别为达到的点,同样也可以防止走重复点的作用。

源码如下:
package com.test;

import java.util.Stack;
class Step{
    int x,y,d;
    public Step(int x,int y,int d) {
        this.x = x;//横坐标
        this.y = y;//纵坐标
        this.d = d;//方向
}
}

public class MazeTest {

public static void main(String[] args) {
// 迷宫定义
int[][] maze = {{1,1,1,1,1,1,1,1,1,1},
    {1,0,1,1,1,0,1,1,1,1},
    {1,1,0,1,0,1,1,1,1,1},
    {1,0,1,0,0,0,0,0,1,1},
    {1,0,1,1,1,0,1,1,1,1},
    {1,1,0,0,1,1,0,0,0,1},
    {1,0,1,1,0,0,1,1,0,1},
    {1,1,1,1,1,1,1,1,1,1}};
int[][] move = {{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};
    Stack s = new Stack();
    Stack s1 = new Stack();
    int a = path(maze, move, s);
    while(!s.isEmpty()){
    Step step = s.pop();
    System.out.println(step.x+":"+step.y);
    }
}
public static int path(int[][] maze,int[][] move,Stack s){
    Step temp = new Step(1,1,-1); //起点
    s.push(temp);
    while(!s.isEmpty()){
        temp = s.pop();
        int x = temp.x;
        int y = temp.y;
        int d = temp.d+1;
    while(d<8){
        int i = x + move[d][0];
        int j = y + move[d][1];
        if(maze[i][j] == 0){ //该点可达
        temp = new Step(i,j,d); //到达新点
        s.push(temp);
        x = i;
        y = j;
    maze[x][y] = -1; //到达新点,标志已经到达
    if(x == 6 && y == 8){
        return 1; //到达出口,迷宫有路,返回1
    }else{
        d = 0; //重新初始化方向
    }
}else{
    d++; //改变方向
    }
    }
}
    return 0;
}

}                            

代码2:

import java.util.*;

class Position{
    public Position(){

    }

    public Position(int row, int col){
        this.col = col;
        this.row = row;
    }

    public String toString(){
        return "(" + row + " ," + col + ")";
    }

    int row;
    int col;
}

class Maze{
    public Maze(){
        maze = new int[15][15];
        stack = new Stack<Position>();
        p = new boolean[15][15];
    }

    /*
     * 构造迷宫
     */
    public void init(){
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入迷宫的行数");
        row = scanner.nextInt();
        System.out.println("请输入迷宫的列数");
        col = scanner.nextInt();
        System.out.println("请输入" + row + "行" + col + "列的迷宫");
        int temp = 0;
        for(int i = 0; i < row; ++i) {
            for(int j = 0; j < col; ++j) {
                temp = scanner.nextInt();
                maze[i][j] = temp;
                p[i][j] = false;
            }
        }
    }

    /*
     * 回溯迷宫,查看是否有出路
     */
    public void findPath(){
        // 给原始迷宫的周围家一圈围墙
        int temp[][] = new int[row + 2][col + 2];
        for(int i = 0; i < row + 2; ++i) {
            for(int j = 0; j < col + 2; ++j) {
                temp[0][j] = 1;
                temp[row + 1][j] = 1;
                temp[i][0] = temp[i][col + 1] = 1;
            }
        }
        // 将原始迷宫复制到新的迷宫中
        for(int i = 0; i < row; ++i) {
            for(int j = 0; j < col; ++j) {
                temp[i + 1][j + 1] = maze[i][j];
            }
        }
        // 从左上角开始按照顺时针开始查询

        int i = 1;
        int j = 1;
        p[i][j] = true;
        stack.push(new Position(i, j));
        while (!stack.empty() && (!(i == (row) && (j == col)))) {

            if ((temp[i][j + 1] == 0) && (p[i][j + 1] == false)) {
                p[i][j + 1] = true;
                stack.push(new Position(i, j + 1));
                j++;
            } else if ((temp[i + 1][j] == 0) && (p[i + 1][j] == false)) {
                p[i + 1][j] = true;
                stack.push(new Position(i + 1, j));
                i++;
            } else if ((temp[i][j - 1] == 0) && (p[i][j - 1] == false)) {
                p[i][j - 1] = true;
                stack.push(new Position(i, j - 1));
                j--;
            } else if ((temp[i - 1][j] == 0) && (p[i - 1][j] == false)) {
                p[i - 1][j] = true;
                stack.push(new Position(i - 1, j));
                i--;
            } else {
                stack.pop();
                if(stack.empty()){
                    break;
                }
                i = stack.peek().row;
                j = stack.peek().col;
            }

        }

        Stack<Position> newPos = new Stack<Position>();
        if (stack.empty()) {
            System.out.println("没有路径");
        } else {
            System.out.println("有路径");
            System.out.println("路径如下:");
            while (!stack.empty()) {
                Position pos = new Position();
                pos = stack.pop();
                newPos.push(pos);
            }
        }

        /*
         * 图形化输出路径
         * */

        String resault[][]=new String[row+1][col+1];
        for(int k=0;k<row;++k){
            for(int t=0;t<col;++t){
                resault[k][t]=(maze[k][t])+"";
            }
        }
        while (!newPos.empty()) {
            Position p1=newPos.pop();
            resault[p1.row-1][p1.col-1]="#";

        }

        for(int k=0;k<row;++k){
            for(int t=0;t<col;++t){
                System.out.print(resault[k][t]+"\t");
            }
            System.out.println();
        }

    }

    int maze[][];
    private int row = 9;
    private int col = 8;
    Stack<Position> stack;
    boolean p[][] = null;
}

class hello{
    public static void main(String[] args){
        Maze demo = new Maze();
        demo.init();
        demo.findPath();
    }
}
时间: 2025-01-18 03:43:13

java实现迷宫算法--转的相关文章

Java算法分析与设计视频教程下载

下载地址:http://pan.baidu.com/s/1i4pMZ9z 密码:v9ra 算法分析与设计Java版,是一套实用型算法课程.通过本课程的学习,学员可以掌握以下技术点:线性结构与顺序表.单向链表.循环链表.栈的基本概念.链式堆栈.中缀表达式.队列.链式队列.串.MyString.Brute-Force算法.MySet类实现.矩阵类.递归算法.哈夫曼树.希尔排序.HashTable算法等内容. 第一讲.算法基本概述.抽象数据类型 第二讲.算法的设计目标.时间复杂度和空间复杂度 第三讲.

Java实战应用视频教程之Java算法分析与设计

实战应用Java算法分析与设计(链表.二叉树.哈夫曼树.图.动态规划.HashTable算法)适合人群:中级课时数量:38课时用到技术:Java算法涉及项目:案例应用实战咨询qq:1840215592课程简介:算法分析与设计Java版,是一套实用型算法课程.通过本课程的学习,学员可以掌握以下技术点:线性结构与顺序表.单向链表.循环链表.栈的基本概念.链式堆栈.中缀表达式.队列.链式队列.串.MyString.Brute-Force算法.MySet类实现.矩阵类.递归算法.哈夫曼树.希尔排序.Ha

Java多线程学习(吐血超详细总结)

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 目录(?)[-] 一扩展javalangThread类 二实现javalangRunnable接口 三Thread和Runnable的区别 四线程状态转换 五线程调度 六常用函数说明 使用方式 为什么要用join方法 七常见线程名词解释 八线程同步 九线程数据传递 本文主要讲了java中多线程的使用方法.线程同步.线程数据传递.线程状态及相应的一些线程函数用法.概述等. 首先讲一下进程和线程

Java TM 已被阻止,因为它已过时需要更新的解决方法

公司的堡垒机需要通过浏览器登陆,且该堡垒机的网站需要Java的支持,最近通过浏览器登陆之后总是提示"java TM 已被阻止,因为它已过时需要更新的解决方法"导致登陆之后不能操作, 但是操作系统中确实已经安装了比较新的JDK,安装的JDK版本是jdk-7u67-windows-i586,因为太烦人,所以决定搞清楚报错的原因,一劳永逸,彻底解决这个问题 准备工作:安装JDK,安装版本jdk-7u67-windows-i586.exe,因为机器的Eclipse还依赖64位的JDK,所以另安

Java四种线程池newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor

介绍new Thread的弊端及Java四种线程池的使用,对Android同样适用.本文是基础篇,后面会分享下线程池一些高级功能. 1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? Java new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub } }).start(); 1 2 3 4 5 6 7 new Thread(new

由@NotNull 注解引出的关于Java空指针的控制(转)

Java 小技巧和在java应用避免NullPonintException的最佳方法 在java应用程序中,一个NullPonintException(空指针异常)是最好解决(问题)的方法.同时,空指针也是写健壮的顺畅运行的代码的关键.“预防好过治疗”这句话也同样适用于令人不爽的NullPonintException.通过应用防御性的编码技术和在遵守多个部分之间的约定,你可以再很大程度上避免NullPointException.下面的这些java小技巧可以最小化像!=null这种检查的代码.作为

Java注解(2)-注解处理器(运行时|RetentionPolicy.RUNTIME)

如果没有用来读取注解的工具,那注解将基本没有任何作用,它也不会比注释更有用.读取注解的工具叫作注解处理器.Java提供了两种方式来处理注解:第一种是利用运行时反射机制:另一种是使用Java提供的API来处理编译期的注解. 反射机制方式的注解处理器 仅当定义的注解的@Retention为RUNTIME时,才能够通过运行时的反射机制来处理注解.下面结合例子来说明这种方式的处理方法. Java中的反射API(如java.lang.Class.java.lang.reflect.Field等)都实现了接

jvm系列(一):java类的加载机制

java类的加载机制 原文:http://www.cnblogs.com/ityouknow/p/5603287.html 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构.类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口. 类加载器并不需要等到某个

Java注解(1)-注解基础

注解(Annotation)是在JAVA5中开始引入的,它为在代码中添加信息提供了一种新的方式.注解在一定程度上把元数据与源代码文件结合在一起,正如许多成熟的框架(Spring)所做的那样.那么,注解到底可以做什么呢? 1.注解的作用. 提供用来完整地描述程序所需要的信息,如编译期校验程序信息. 生成描述符文件,或生成新类的定义. 减轻编写"样板"代码(配置文件)的负担,可以使用注解自动生成. 更加干净易读的代码. 编译期类型检查. 2.Java提供的注解 Java5内置了一些原生的注