迷宫

迷宫

用 Java 写了一个迷宫程序,算法总结起来就是将“死路”彻底封死(我称之为砌砖),最后只剩下“活路”就是查找到的迷宫通行路径了。代码如下:

package org.iword;

/**
 * @文件名: org.iword.Main.java
 * @作者 : iword
 * @日期 : 2014年6月19日 下午11:28:29
 * @版本 : 1.0
 * @描术 :
 *
 *     ALL RIGHTS RESERVED,COPYRIGHT(C) FCH LIMITED 2014
 */

public class Main {
    public static void main(String[] args)
    {
        int[][] numbers = { 
                { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
                { 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1 },
                { 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1 },
                { 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1 },
                { 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1 },
                { 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 },
                { 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
                { 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1 },
                { 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1 } };
        Status[][] status = getMap(numbers); // 获取地图
        Maze maze = new Maze(status, 0, 2); // 新建迷宫,入口坐标为(0, 2)
        maze.drawMap(); // 绘制地图
        System.out.println();
        maze.drawPath(); // 绘制路径
    }

    // 根据整型二维数组获取地图(直接用Status[][]难以排版且不便于观察)
    private static Status[][] getMap(int[][] numbers)
    {
        Status[][] map = new Status[numbers.length][numbers[0].length];
        for (int i = 0; i < numbers.length; i++) {
            for (int j = 0; j < numbers[i].length; j++) {
                map[i][j] = (0 == numbers[i][j] 
                        ? Status.PASSABLE : Status.IMPASSABLE);
            }
        }

        return map;
    }
}

package org.iword;

import java.util.Arrays;

/**
 * @文件名: org.iword.Maze.java
 * @作者 : iword
 * @日期 : 2014年6月19日 下午11:02:48
 * @版本 : 1.0
 * @描术 : 
 * 1.地图每个坐标分为三种状态:可通过、不可通过、已通过;
 * 2.从入口开始,查找当前位置上、右、下、左是否有可供前进的下一坐标:
 *   (1)下一坐标为可通过状态则将当前坐标设定为已通过并移到下一步;
 *   (2)下一坐标为已通过状态则将当前坐标设定为不可通过(相当于砌了一块砖进行封堵)并移到下一步;
 *   (3)以上两步优先返回可通过状态的位置,没有可供前进的下一步则判定地图没有出口,结束程序。
 * 以上总结起来就是,将“死路”用砖块彻底封死,最后只剩“活路”。
 * 
 *
 *     ALL RIGHTS RESERVED,COPYRIGHT(C) FCH LIMITED 2014
 */

public class Maze {
    private class Location {
        public int x;
        public int y;

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

        // 将当前位置上、右、下、左四个位置以数组的形式返回
        public Location[] getRound()
        {
            Location[] round = { 
                    new Location(x, y + 1),
                    new Location(x + 1, y), 
                    new Location(x, y - 1),
                    new Location(x - 1, y) };
            
            return round;
        }
    }

    private final Status[][] originalMap; // 原始地图
    private Status[][] pathMap; // 路径地图
    private final Location entry; // 入口位置

    public Maze(Status[][] status, int x, int y)
    {
        this.originalMap = status;
        this.pathMap = copy(); // 复制地图用于查找路径以免破坏原始地图
        this.entry = new Location(x, y);
    }

    // 复制地图
    private Status[][] copy()
    {
        Status[][] mapCopy = new Status[this.originalMap.length][];
        for (int i = 0; i < this.originalMap.length; i++) {
            mapCopy[i] = Arrays.copyOf(originalMap[i], originalMap[i].length);
        }
        
        return mapCopy;
    }

    // 查找路径
    private void searchPath()
    {
        Location current = entry;
        Location next = null;
        while (!isExit(current)) {
            next = nextStep(current); // 获取下一步坐标
            switch (getStatus(next)) {
            case PASSABLE:
                // 下一坐标为可通过则将当前坐标设定为已通过
                setStatus(current, Status.PASSED);
                break;
            case PASSED:
                // 下一步为已通过则将当前坐标设定为不可通过(砌砖)
                setStatus(current, Status.IMPASSABLE);
                break;
            default:
                throw new RuntimeException("查找路径出错!");
            }
            current = next;
        }
        setStatus(current, Status.PASSED); // 将最后的出口设定为已通过
    }

    // 检测 location 是否为出口
    private boolean isExit(Location location)
    {
        if (!isInside(location)) {
            return false;
        }
        if (location.x == entry.x && location.y == entry.y) {
            return false;
        }
        if (0 == location.x || this.pathMap[0].length - 1 == location.x) {
            return true;
        }
        if (0 == location.y || this.pathMap.length - 1 == location.y) {
            return true;
        }
        return false;
    }

    // 查找 current 上、右、下、左可供前进的位置
    private Location nextStep(Location current)
    {
        Location next = null;
        for (Location location : current.getRound()) {
            if (isInside(location) && Status.IMPASSABLE != getStatus(location)) {
                next = location;
                if (Status.PASSABLE == getStatus(next)) {
                    return next;
                }
            }
        }
        if (null == next) {
            throw new RuntimeException("地图错误,没有出口!");
        }

        return next;
    }

    // 检测 location 是否在地图内
    private boolean isInside(Location location)
    {
        if (null == location) {
            return false;
        }
        if (location.x < 0 || location.x >= this.originalMap[0].length) {
            return false;
        }
        if (location.y < 0 || location.y >= this.originalMap.length) {
            return false;
        }
        return true;
    }

    // 获取 location 处的通行状态
    private Status getStatus(Location location)
    {
        return this.pathMap[location.y][location.x];
    }

    // 设定 location 处的通行状态
    private void setStatus(Location location, Status status)
    {
        this.pathMap[location.y][location.x] = status;
    }

    // 绘制地图
    public void drawMap()
    {
        draw(this.originalMap);
    }

    // 绘制路径
    public void drawPath()
    {
        searchPath();
        // 将砌死的坐标状态恢复原样
        for (int i = 0; i < this.originalMap.length; i++) {
            for (int j = 0; j < this.originalMap[i].length; j++) {
                if (originalMap[i][j] != pathMap[i][j]
                        && Status.PASSED != pathMap[i][j]) {
                    pathMap[i][j] = originalMap[i][j];
                }
            }
        }
        draw(this.pathMap);
    }

    // 绘制
    private void draw(Status[][] status)
    {
        for (Status[] elements : status) {
            for (Status element : elements) {
                switch (element) {
                case PASSABLE:
                    System.out.print("口"); // 可通过状态
                    break;
                case IMPASSABLE:
                    System.out.print("田"); // 不可通过状态
                    break;
                case PASSED:
                    System.out.print("="); // 已通过状态
                    break;
                }
            }
            System.out.println();
        }
    }
}

package org.iword;

/**
 * @文件名: org.iword.Status.java
 * @作者 : iword
 * @日期 : 2014年6月19日 下午11:03:04
 * @版本 : 1.0
 * @描术 : 用于表示地图上每个坐标点的通行状态
 *
 *     ALL RIGHTS RESERVED,COPYRIGHT(C) FCH LIMITED 2014
 */

public enum Status {
    PASSABLE, IMPASSABLE, PASSED
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值