所以我目前正在处理的任务相当简单。我必须找到每个给定迷宫内给定起点的所有导出,并将路径打印到屏幕上。可以有多个导出。迷宫可以如下所示:
#####.###
#.....#.#
#.#####.#
#.#.....#
#.#.###.#
#.#.#.#.#
#.....#.#
#########
正方形就是正方形。点是 WhiteSquare,主题标签是 BlackSquare,它们都是 Square 的子类。 Opening 是 WhiteSquare 的子类。
这个想法是在我当前所在的方 block 的每个邻居上调用 go() 。黑色方 block 中的方法 go() 不执行任何操作,因此只有白色方 block 在这方面起作用。每次调用 go() 时,都会将包含所有先前访问过的方 block 的列表副本作为参数发送,这样它就不会在前一个邻居上调用 go()。这是因为我希望该算法也适用于循环迷宫。一旦我遇到一个空位,我就会将该路径添加到起始方 block 的可能导出列表(列表列表)中。这是代码:
public void go(ArrayList<Rute> path, WhiteSquare startSquare) {
ArrayList<Rute> pathCopy = path;
pathCopy.add(this);
if (this instanceof Opening) {
startSquare.addPossibleExit(pathCopy);
return;
}
for (Square neighbour : this.getNeighbours()) {
if (!path.contains(neighbour)) {
neighbour.go(pathCopy, startSquare);
}
}
}
System.out.println(startSquare.exits) 找到空位后将打印正确的路径。一切都很好。然而,如果在找到空位后有更多的方 block 要经过,那么导出中的正确路径将以某种方式开始在列表本身内增长,即使在添加了它之后也是如此。我不明白。上面迷宫中 startRoute 为 (3, 1) 的示例(伪代码):
System.out.println(Square.toString() + " go. " + Exits: " + startSquare.getExits())
if (this instanceof Opening) {print("Opening found!")}
将打印出:
(3, 1) go. Exits: []
(2, 1) go. Exits: []
(1, 1) go. Exits: []
(1, 2) go. Exits: []
(1, 3) go. Exits: []
(1, 4) go. Exits: []
(1, 5) go. Exits: []
(0, 5) go. Exits: []
Opening found!
(4, 1) go. Exits: [[(3, 1), (2, 1), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (0, 5)]]
(5, 1) go. Exits: [[(3, 1), (2, 1), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (0, 5), (4, 1)]]
(6, 1) go. Exits: [[(3, 1), (2, 1), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (0, 5), (4, 1), (5, 1)]]
我无法解释这里发生了什么。我不希望路径在添加到导出后继续增长。
最佳答案
pathCopy
不是 new ArrayList
,它是对 path
的引用,当您添加到 pathCopy
时,它实际上添加到 path
。
您可以创建一个新的ArrayList
,然后使用.addAll(path)
将所有值复制到新的ArrayList
。
Java 中的每个变量都是指针,除了基本类型(如 int、bool)。 当您分配“复杂”类型时,它分配的是指针而不是值。
关于引用和值(value)的解释可以参见here
关于java - 不知何故,在递归过程中,对象在 list.add(object) 之后发生了变异。解释?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49819559/