你问这个迷宫递归拼图四个问题在过去的五年结束小时,这证明了它是多么复杂。整个概念1/1迷宫格吸引了我,我想出了一个类应该使它更简单很多。如果你需要做递归,那么它对你没有用处,但是如果你可以使用它,它将消除它的大部分复杂性。
有两个类,一个Enum。
首先,enum定义了您希望在网格中移动的方向,并根据其移动确定一次一个新的索引。
enum Direction {
UP(-1, 0),
DOWN(1, 0),
LEFT(0, -1),
RIGHT(0, 1);
private final int rowSteps;
private final int colSteps;
private Direction(int rowSteps, int colSteps) {
this.rowSteps = rowSteps;
this.colSteps = colSteps;
}
public int getNewRowIdx(int currentRowIdx) {
return (currentRowIdx + getRowSteps());
}
public int getNewColIdx(int currentColIdx) {
return (currentColIdx + getColSteps());
}
public int getRowSteps() {
return rowSteps;
}
public int getColSteps() {
return colSteps;
}
};
主类被称为MazePosition
(如下)。首先,你设置的迷宫网双阵列进去,通过其int[][]
构造函数和静态存储实例:
private static final MazePosition MAZE_HOLDER = new MazePosition(MAZE_GRID);
(此步骤可以设计更好,但它的工作原理)
设置完成后迷宫网格(其是一次性唯一,每次执行),则X/Y构造用于声明的初始位置:
MazePosition pos = new MazePosition(0, 0);
在这之后,只要将作为必要的:
pos = pos.getNeighbor(Direction.RIGHT);
pos = pos.getNeighbor(Direction.RIGHT);
pos = pos.getNeighbor(Direction.DOWN);
...
每个位置的值由pos.getValue()
或pos.isPath()
检索 - 我认为1
是“墙”,0
是“路径”。 (顺便说一句:巨大的2d阵列应该包含一位booleans
,而不是4字节的ints
,但看在阵列的代码是合理的int
s,并且不与布尔值...注意它至少应该改为byte
秒)
所以对于运动,如果你试图得到一个邻居时,有没有,比如向左移动的左边缘处,一个IllegalStateException
被抛出。使用is*Edge()
函数来避免这种情况。
MazePosition类还有一个方便的调试函数,称为getNineByNine()
,它返回数组值为9x9的网格(作为字符串),其中中间项是当前位置。
import java.util.Arrays;
import java.util.Objects;
class MazePosition {
//state
private static int[][] MAZE_GRID;
private final int rowIdx;
private final int colIdx;
//internal
private final int rowIdxMinus1;
private final int colIdxMinus1;
public MazePosition(int[][] MAZE_GRID) {
if(this.MAZE_GRID != null) {
throw new IllegalStateException("Maze double-array already set. Use x/y constructor.");
}
MazePosition.MAZE_GRID = MAZE_GRID;
//TODO: Crash if null or empty, or sub-arrays null or empty, or unequal lengths, or contain anything but 0 or -1.
rowIdx = -1;
colIdx = -1;
rowIdxMinus1 = -1;
colIdxMinus1 = -1;
}
public MazePosition(int rowIdx, int colIdx) {
if(MazePosition.MAZE_GRID == null) {
throw new IllegalStateException("Must set maze double-array with: new MazePosition(int[][]).");
}
if(rowIdx < 0 || rowIdx >= MazePosition.getRowCount()) {
throw new IllegalArgumentException("rowIdx (" + rowIdx + ") is invalid.");
}
if(colIdx < 0 || colIdx >= MazePosition.getColumnCount()) {
throw new IllegalArgumentException("colIdx (" + colIdx + ") is invalid.");
}
this.rowIdx = rowIdx;
this.colIdx = colIdx;
rowIdxMinus1 = (rowIdx - 1);
colIdxMinus1 = (colIdx - 1);
}
public boolean isPath() {
return (getValue() == 0); //1???
}
public int getValue() {
return MazePosition.MAZE_GRID[getRowIdx()][getColumnIdx()];
}
public int getRowIdx() {
return rowIdx;
}
public int getColumnIdx() {
return colIdx;
}
public MazePosition getNeighbor(Direction dir) {
Objects.requireNonNull(dir, "dir");
return (new MazePosition(
dir.getNewRowIdx(getRowIdx()),
dir.getNewColIdx(getColumnIdx())));
}
public MazePosition getNeighborNullIfEdge(Direction dir) {
if(isEdgeForDirection(dir)) {
return null;
}
return getNeighbor(dir);
}
public int getNeighborValueNeg1IfEdge(Direction dir) {
MazePosition pos = getNeighborNullIfEdge(dir);
return ((pos == null) ? -1 : pos.getValue());
}
public static final int getRowCount() {
return MAZE_GRID.length;
}
public static final int getColumnCount() {
return MAZE_GRID[0].length;
}
public boolean isEdgeForDirection(Direction dir) {
Objects.requireNonNull(dir);
switch(dir) {
case UP: return isTopEdge();
case DOWN: return isBottomEdge();
case LEFT: return isLeftEdge();
case RIGHT: return isRightEdge();
}
throw new IllegalStateException(toString() + ", dir=" + dir);
}
public boolean isLeftEdge() {
return (getColumnIdx() == 0);
}
public boolean isTopEdge() {
return (getRowIdx() == 0);
}
public boolean isBottomEdge() {
return (getRowIdx() == rowIdxMinus1);
}
public boolean isRightEdge() {
return (getColumnIdx() == colIdxMinus1);
}
public String toString() {
return "[" + getRowIdx() + "," + getColumnIdx() + "]=" + getValue();
}
public String getNineByNine() {
int[][] nineByNine = new int[3][3];
//Middle row
nineByNine[1][1] = getValue();
nineByNine[1][0] = getNeighborValueNeg1IfEdge(Direction.LEFT);
nineByNine[1][2] = getNeighborValueNeg1IfEdge(Direction.RIGHT);
//Top
MazePosition posUp = getNeighborNullIfEdge(Direction.UP);
if(posUp != null) {
nineByNine[0][0] = posUp.getNeighborValueNeg1IfEdge(Direction.LEFT);
nineByNine[0][1] = posUp.getValue();
nineByNine[0][2] = posUp.getNeighborValueNeg1IfEdge(Direction.RIGHT);
}
//Bottom
MazePosition posDown = getNeighborNullIfEdge(Direction.DOWN);
if(posDown != null) {
nineByNine[2][0] = posDown.getNeighborValueNeg1IfEdge(Direction.LEFT);
nineByNine[2][1] = posDown.getValue();
nineByNine[2][2] = posDown.getNeighborValueNeg1IfEdge(Direction.RIGHT);
}
String sLS = System.getProperty("line.separator", "\r\n");
return "Middle position in 9x9 grid is *this*: " + toString() + sLS +
Arrays.toString(nineByNine[0]) + sLS +
Arrays.toString(nineByNine[1]) + sLS +
Arrays.toString(nineByNine[2]);
}
}
这是什么没有,是“碰撞检测”或任何实际上为你找出迷宫路径。它只是在整个网格中移动,无论它是否穿过墙壁。可以很容易地添加一些getNeighborIfNotWall(Direction)
和isWallToLeft()
函数,但我会把它留给你。;)
(事实上,这些类没有太多的变化,可以用来遍历任何二维数组,但我可能会添加对角方向,如UP_LEFT
,以及移动多个步骤的能力,如getNeighbor(3, Direction.DOWN)
)。
这里的一个示范的使用:
public class MazePosDemo {
private static final int[][] MAZE_GRID = new int[][] {
//mega maze grid goes here...
};
private static final MazePosition MAZE_HOLDER = new MazePosition(MAZE_GRID);
public static final void main(String[] ignored) {
MazePosition pos = new MazePosition(0, 0);
System.out.println("start: " + pos);
pos = pos.getNeighbor(Direction.RIGHT);
System.out.println("right: " + pos);
pos = pos.getNeighbor(Direction.RIGHT);
System.out.println("right: " + pos);
pos = pos.getNeighbor(Direction.DOWN);
System.out.println("down: " + pos);
pos = pos.getNeighbor(Direction.DOWN);
System.out.println("down: " + pos);
pos = pos.getNeighbor(Direction.RIGHT);
System.out.println("right: " + pos);
pos = pos.getNeighbor(Direction.DOWN);
System.out.println("down: " + pos);
pos = pos.getNeighbor(Direction.LEFT);
System.out.println("left: " + pos);
pos = pos.getNeighbor(Direction.UP);
System.out.println("up: " + pos);
pos = pos.getNeighbor(Direction.UP);
System.out.println("up: " + pos);
System.out.println(pos.getNineByNine());
}
}
输出
[C:\java_code\]java MazePosDemo
start: [0,0]=1
right: [0,1]=1
right: [0,2]=1
down: [1,2]=1
down: [2,2]=1
right: [2,3]=1
down: [3,3]=0
left: [3,2]=1
up: [2,2]=1
up: [1,2]=1
Middle position in 9x9 grid is *this*: [1,2]=1
[1, 1, 1]
[0, 1, 0]
[0, 1, 1]
而这里的整个源代码文件,包含上述所有(包括巨型迷宫阵列)的:
//Needed only by MazePosition
import java.util.Arrays;
import java.util.Objects;
enum Direction {
UP(-1, 0),
DOWN(1, 0),
LEFT(0, -1),
RIGHT(0, 1);
//config
private final int rowSteps;
private final int colSteps;
private Direction(int rowSteps, int colSteps) {
this.rowSteps = rowSteps;
this.colSteps = colSteps;
}
public int getNewRowIdx(int currentRowIdx) {
return (currentRowIdx + getRowSteps());
}
public int getNewColIdx(int currentColIdx) {
return (currentColIdx + getColSteps());
}
public int getRowSteps() {
return rowSteps;
}
public int getColSteps() {
return colSteps;
}
};
class MazePosition {
//config
private static int[][] MAZE_GRID;
private final int rowIdx;
private final int colIdx;
//internal
private final int rowIdxMinus1;
private final int colIdxMinus1;
public MazePosition(int[][] MAZE_GRID) {
if(this.MAZE_GRID != null) {
throw new IllegalStateException("Maze double-array already set. Use x/y constructor.");
}
MazePosition.MAZE_GRID = MAZE_GRID;
//TODO: Crash if null or empty, or sub-arrays null or empty, or unequal lengths, or contain anything but 0 or -1.
rowIdx = -1;
colIdx = -1;
rowIdxMinus1 = -1;
colIdxMinus1 = -1;
}
public MazePosition(int rowIdx, int colIdx) {
if(MazePosition.MAZE_GRID == null) {
throw new IllegalStateException("Must set maze double-array with: new MazePosition(int[][]).");
}
if(rowIdx < 0 || rowIdx >= MazePosition.getRowCount()) {
throw new IllegalArgumentException("rowIdx (" + rowIdx + ") is invalid.");
}
if(colIdx < 0 || colIdx >= MazePosition.getColumnCount()) {
throw new IllegalArgumentException("colIdx (" + colIdx + ") is invalid.");
}
this.rowIdx = rowIdx;
this.colIdx = colIdx;
rowIdxMinus1 = (rowIdx - 1);
colIdxMinus1 = (colIdx - 1);
}
public boolean isPath() {
return (getValue() == 0); //1???
}
public int getValue() {
return MazePosition.MAZE_GRID[getRowIdx()][getColumnIdx()];
}
public int getRowIdx() {
return rowIdx;
}
public int getColumnIdx() {
return colIdx;
}
public MazePosition getNeighbor(Direction dir) {
Objects.requireNonNull(dir, "dir");
return (new MazePosition(
dir.getNewRowIdx(getRowIdx()),
dir.getNewColIdx(getColumnIdx())));
}
public MazePosition getNeighborNullIfEdge(Direction dir) {
if(isEdgeForDirection(dir)) {
return null;
}
return getNeighbor(dir);
}
public int getNeighborValueNeg1IfEdge(Direction dir) {
MazePosition pos = getNeighborNullIfEdge(dir);
return ((pos == null) ? -1 : pos.getValue());
}
public static final int getRowCount() {
return MAZE_GRID.length;
}
public static final int getColumnCount() {
return MAZE_GRID[0].length;
}
public boolean isEdgeForDirection(Direction dir) {
Objects.requireNonNull(dir);
switch(dir) {
case UP: return isTopEdge();
case DOWN: return isBottomEdge();
case LEFT: return isLeftEdge();
case RIGHT: return isRightEdge();
}
throw new IllegalStateException(toString() + ", dir=" + dir);
}
public boolean isLeftEdge() {
return (getColumnIdx() == 0);
}
public boolean isTopEdge() {
return (getRowIdx() == 0);
}
public boolean isBottomEdge() {
return (getRowIdx() == rowIdxMinus1);
}
public boolean isRightEdge() {
return (getColumnIdx() == colIdxMinus1);
}
public String toString() {
return "[" + getRowIdx() + "," + getColumnIdx() + "]=" + getValue();
}
public String getNineByNine() {
int[][] nineByNine = new int[3][3];
//Middle row
nineByNine[1][1] = getValue();
nineByNine[1][0] = getNeighborValueNeg1IfEdge(Direction.LEFT);
nineByNine[1][2] = getNeighborValueNeg1IfEdge(Direction.RIGHT);
//Top
MazePosition posUp = getNeighborNullIfEdge(Direction.UP);
if(posUp != null) {
nineByNine[0][0] = posUp.getNeighborValueNeg1IfEdge(Direction.LEFT);
nineByNine[0][1] = posUp.getValue();
nineByNine[0][2] = posUp.getNeighborValueNeg1IfEdge(Direction.RIGHT);
}
//Bottom
MazePosition posDown = getNeighborNullIfEdge(Direction.DOWN);
if(posDown != null) {
nineByNine[2][0] = posDown.getNeighborValueNeg1IfEdge(Direction.LEFT);
nineByNine[2][1] = posDown.getValue();
nineByNine[2][2] = posDown.getNeighborValueNeg1IfEdge(Direction.RIGHT);
}
String sLS = System.getProperty("line.separator", "\r\n");
return "Middle position in 9x9 grid is *this*: " + toString() + sLS +
Arrays.toString(nineByNine[0]) + sLS +
Arrays.toString(nineByNine[1]) + sLS +
Arrays.toString(nineByNine[2]);
}
}
public class MazePosDemo {
private static final int[][] MAZE_GRID = new int[][] {
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1},
{1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,0,1,0,1},
{1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,1,0,1,0,1},
{1,0,1,0,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1,0,1,0,1,1,1,0,1,0,1,1,1,1,1,0,1,1,1,0,1,0,1,0,1,1,1,0,1,1,1,0,1},
{1,0,1,0,1,0,1,0,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,1,0,1,0,1,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,1,0,0,0,1},
{1,0,1,1,1,0,1,0,1,1,1,0,1,0,1,0,1,0,1,1,1,1,1,0,1,0,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,0,1,0,1},
{1,0,0,0,0,0,1,0,0,0,0,0,1,0,1,0,1,0,1,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,1},
{1,1,1,0,1,1,1,1,1,1,1,1,1,0,1,0,1,0,1,0,1,0,1,1,1,0,1,1,1,1,1,1,1,0,1,0,1,0,1,1,1,0,1,1,1,1,1,1,1,0,1},
{1,0,1,0,1,0,0,0,0,0,0,0,1,0,1,0,1,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,1},
{1,0,1,0,1,0,1,1,1,1,1,0,1,0,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,0,1,1,1,0,1,0,1,1,1},
{1,0,1,0,1,0,0,0,1,0,1,0,1,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,1},
{1,0,1,0,1,1,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1,0,1,0,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1},
{1,0,1,0,1,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1},
{1,0,1,0,1,0,1,0,1,0,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1,0,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,0,1},
{1,0,0,0,1,0,1,0,1,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,1},
{1,0,1,1,1,0,1,0,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,0,1,1,1,0,1,0,1,1,1,1,1,0,1,1,1,0,1},
{1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,1,0,1,0,1},
{1,1,1,1,1,0,1,1,1,0,1,1,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,0,1,0,1,0,1,0,1,1,1,1,1,0,1,0,1},
{1,0,0,0,1,0,0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,1},
{1,0,1,1,1,1,1,0,1,1,1,0,1,1,1,0,1,0,1,1,1,0,1,0,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,0,1,0,1,0,1,0,1},
{1,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,1,0,1,0,1,0,1,0,1},
{1,1,1,0,1,0,1,1,1,0,1,1,1,0,1,0,1,1,1,1,1,0,1,1,1,0,1,1,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,0,1,0,1,1,1,0,1},
{1,0,0,0,1,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,1},
{1,0,1,1,1,0,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,0,1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1},
{1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,1},
{1,0,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,0,1,0,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,1,1,1,1,0,1,0,1,1,1,0,1,0,1,0,1},
{1,0,0,0,0,0,0,0,1,0,1,0,1,0,1,0,0,0,1,0,1,0,1,0,1,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0,1,0,1,0,0,0,1,0,1,0,1},
{1,0,1,1,1,1,1,0,1,0,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,0,1,1,1,1,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,1,1,1,1,0,1},
{1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,1,0,1},
{1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,0,1,0,1},
{1,0,0,0,1,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,1,0,1},
{1,0,1,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,1,0,1,0,1,0,1},
{1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1}};
private static final MazePosition MAZE_HOLDER = new MazePosition(MAZE_GRID);
public static final void main(String[] ignored) {
MazePosition pos = new MazePosition(0, 0);
System.out.println("start: " + pos);
pos = pos.getNeighbor(Direction.RIGHT);
System.out.println("right: " + pos);
pos = pos.getNeighbor(Direction.RIGHT);
System.out.println("right: " + pos);
pos = pos.getNeighbor(Direction.DOWN);
System.out.println("down: " + pos);
pos = pos.getNeighbor(Direction.DOWN);
System.out.println("down: " + pos);
pos = pos.getNeighbor(Direction.RIGHT);
System.out.println("right: " + pos);
pos = pos.getNeighbor(Direction.DOWN);
System.out.println("down: " + pos);
pos = pos.getNeighbor(Direction.LEFT);
System.out.println("left: " + pos);
pos = pos.getNeighbor(Direction.UP);
System.out.println("up: " + pos);
pos = pos.getNeighbor(Direction.UP);
System.out.println("up: " + pos);
System.out.println(pos.getNineByNine());
}
}
您是否尝试过使用调试器来帮助您弄清楚您的程序可能会做错什么?如果这是我的任务,那就是我开始的地方。 –
看来,它经历了每个方向一次,而十不重复 – user3390133
是的,但为什么?这是因为你的程序逻辑有问题,你必须先确定问题出在哪里。如果没有首先进行调查,你有点过早来到这里。 –