我只想使用最简单的算法生成一些迷宫,但我的迷宫看起来像下面这样:
这是一段Java代码(whatVisit函数工作正常,不要看它):
private void dfs(Point start, boolean[][] visited) {
Point nextCell = whatVisit(start, visited);
if(nextCell == null) // if there's nothing to visit
return;
// mark current cell as visited
visited[start.y][start.x] = true;
// destroy the wall between current cell and the new one
borders[(start.y + nextCell.y)/2][(start.x + nextCell.x)/2] = true;
// start a new search from found cell
dfs(nextCell, visited);
}
private Point whatVisit(Point p, boolean[][] visited) {
Vector<Point>cells = new Vector<Point>(); // to store acessible cells
// lookaround
if(p.x - 2 >= 0 && !visited[p.y][p.x - 2])
cells.add(new Point(p.x - 2, p.y));
if(p.x + 2 < visited[0].length && !visited[p.y][p.x + 2])
cells.add(new Point(p.x + 2, p.y));
if(p.y - 2 >= 0 && !visited[p.y - 2][p.x])
cells.add(new Point(p.x, p.y - 2));
if(p.y + 2 < visited.length && !visited[p.y + 2][p.x])
cells.add(new Point(p.x, p.y + 2));
// instead of Random
Collections.shuffle(cells);
// returns null if there are no acessible cells around
if(cells.size() > 0)
return cells.get(0);
else return null;
}
我知道为什么它不起作用!当DFS最终到达没有可访问单元格的地方时,它就会重新开始。
如何解决此问题并强制正确使用?
感谢。
答案 0 :(得分:1)
实际上我仍然没有得到你想要产生的迷宫的目的。但我有一些建议:
通过随机化坐标创建dfs算法的2或3个起点,这样迷宫就不会单调。
在您的算法中,每次移动只能尝试1个可访问的单元格。尝试在每次移动中访问更多可访问的单元格,以使路径不是完成的单向路径。 (这也是你的dfs在找不到可访问的单元后重新开始的原因)
以下是我上面第二个想法的代码(根据您上面的代码编辑):
private void dfs(Point start, boolean[][] visited) {
ArrayList<Point> nextCell = whatVisit(start, visited);
if(nextCell == null) // if there's nothing to visit
return;
// mark current cell as visited
visited[start.y][start.x] = true;
for (Point next : nextCell) // try new accessible cells
{
// destroy the wall between current cell and the new one
borders[(start.y + next.y)/2][(start.x + next.x)/2] = true;
// start a new search from found cell
dfs(next, visited);
}
}
private ArrayList<Point> whatVisit(Point p, boolean[][] visited) {
Vector<Point>cells = new Vector<Point>(); // to store acessible cells
// lookaround
if(p.x - 2 >= 0 && !visited[p.y][p.x - 2])
cells.add(new Point(p.x - 2, p.y));
if(p.x + 2 < visited[0].length && !visited[p.y][p.x + 2])
cells.add(new Point(p.x + 2, p.y));
if(p.y - 2 >= 0 && !visited[p.y - 2][p.x])
cells.add(new Point(p.x, p.y - 2));
if(p.y + 2 < visited.length && !visited[p.y + 2][p.x])
cells.add(new Point(p.x, p.y + 2));
// returns null if there are no accessible cells around
if(cells.size() > 0)
{
ArrayList<Point> tmp = new ArrayList<Point>();
// randomize how many cell that will be returned
int x = (int)(Math.random()*cells.size()) + 1;
if (x > cells.size())
x = cells.size();
Collections.shuffle(cells);
for (int i = 0; i < x; i++)
tmp.add(cells.get(i));
return tmp;
}
else return null;
}
希望这会有所帮助;)
答案 1 :(得分:1)
看起来你只是在你到达死胡同时拯救并退出。相反,您应该回溯直到找到仍然具有可访问邻居的单元格,并从那里继续算法。通常的方法是使用堆栈:在您访问它们时按下项目,弹出以回溯。像这样:
if (nextCell == null) { // You've reached a dead-end
if (stack.empty()) // base-case, bail out
return;
dfs(stack.pop(), visited); // backtrack
} else {
stack.push(nextCell);
visited[start.y][start.x] = true;
borders[(start.y + nextCell.y)/2][(start.x + nextCell.x)/2] = true;
dfs(nextCell, visited);
}