迷宫
用 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
}