如何更改我的 DFS 迷宫算法以生成多个 path/be 不完美?
How can I change my DFS maze algorithm to generate more than one path/be not perfect?
到目前为止,我得到了一个 DFS 迷宫算法,它让我和完美的迷宫完全符合一条路径。我想知道如何在几乎没有变化的情况下获得不止一条路径来达到我的目的。我应该随机移除墙壁吗?但问题是我不想要完全没有墙壁的空方块...
到目前为止,这是我的算法:
private void computeMaze(){
Random random = new Random();
Stack<Block> stack = new Stack<Block>(); //Stack
Block current = blocks[0][0]; //First cell is the current cell
current.setVisited(true); //Mark as accessed
//Create a count; first cell has been accessed, if no unvisited cells left == 0
int unVisitedCount=ROWS*COLS-1;
//Create a list of neighbors
List<Block> neighbors;
Block next;
while(unVisitedCount > 0) {
//Find neighbor collection (unreachable)
neighbors = current.findNeighbors();
//If the current cell has unvisited neighbors then:
if(neighbors.size() > 0) {
//Randomly select a neighbor from this list
int index = random.nextInt(neighbors.size());
next = neighbors.get(index);
//Stack the current cell
stack.push(current);
//Remove the walls between the current maze cell and the randomly selected neighbor cell
this.removeWall(current,next);
//Mark the neighbor cell as visited and use it as the current cell
next.setVisited(true);
current = next;
//If an access is marked, the counter is decreased by 1
unVisitedCount--;
}
else if(stack.isEmpty() == false) {//If the current maze cell does not have an unreachable adjacent maze cell, and the stack is not empty
/*
1.The maze unit at the top of the stack comes out of the stack
2.Make it the current maze unit
*/
Block cell = stack.pop();
current = cell;
}
}
}
//Find neighbors as well as the getneighbors methods:
//Find out whether the current cell has an unreachable neighbor cell
public List<Block> findNeighbors() {
//The neighbors are divided into upper, lower, left and right
List<Block> res = new ArrayList<Block>();
Block top = this.getNeighbor(0,false);
Block right = this.getNeighbor(1,false);
Block bottom = this.getNeighbor(2,false);
Block left = this.getNeighbor(3,false);
if(top != null){
res.add(top);
}
if(right != null){
res.add(right);
}
if(bottom != null){
res.add(bottom);
}
if(left != null){
res.add(left);
}
return res;//Return neighbor array
}
//Get neighbors according to direction
public Block getNeighbor(int type,boolean lose_visited) {
Block neighbor;
int neighbor_i = 0, neighbor_j = 0;
switch(type) {
case 0:
neighbor_i = this.i-1;
neighbor_j = this.j;
break;
case 1:
neighbor_i = this.i;
neighbor_j = this.j+1;
break;
case 2:
neighbor_i = this.i+1;
neighbor_j = this.j;
break;
case 3:
neighbor_i = this.i;
neighbor_j = this.j-1;
break;
}
Block[][] blocks = panel.blocks;
//It's beyond the boundary, therefore no neighbor
if(neighbor_i < 0 || neighbor_j < 0 || neighbor_i >= panel.ROWS || neighbor_j >= panel.COLS) {
neighbor = null;
}
//The dimensions are permitted, neighbor is found
else {
//Find the neighbor, either top/bottom/left/right
neighbor = blocks[neighbor_i][neighbor_j];
//Judge whether it is accessed. If it is accessed, null is returned
if(neighbor.visited && !lose_visited) {//lose_visited equals true to ignore access
neighbor = null;
}
}
return neighbor;
}
要制作包含多个解决方案的迷宫,您需要移除将解决方案路径连接到 non-solution 路径的墙壁。然后将 non-solution 路径添加到备用解决方案。
您可能还想移除多个 non-solution 路径之间的一些墙,让它变得有趣。
留空区的问题比较有意思。如果是 4 向连接,您可以从一个单元格中移除所有 4 面墙,因此您需要检查相邻单元格是否有墙连接到角落。
然后问题是移除是否微不足道 - 连接是否靠近 2 条路径已经连接的点?
- 确定所有具有该连接的墙部分 属性,
- 并且不要导致琐碎的解决方案
- 检查移除该墙部分是否不会破坏拐角规则。
- 随机select一个
- 重复直到你有足够的替代解决方案。
到目前为止,我得到了一个 DFS 迷宫算法,它让我和完美的迷宫完全符合一条路径。我想知道如何在几乎没有变化的情况下获得不止一条路径来达到我的目的。我应该随机移除墙壁吗?但问题是我不想要完全没有墙壁的空方块...
到目前为止,这是我的算法:
private void computeMaze(){
Random random = new Random();
Stack<Block> stack = new Stack<Block>(); //Stack
Block current = blocks[0][0]; //First cell is the current cell
current.setVisited(true); //Mark as accessed
//Create a count; first cell has been accessed, if no unvisited cells left == 0
int unVisitedCount=ROWS*COLS-1;
//Create a list of neighbors
List<Block> neighbors;
Block next;
while(unVisitedCount > 0) {
//Find neighbor collection (unreachable)
neighbors = current.findNeighbors();
//If the current cell has unvisited neighbors then:
if(neighbors.size() > 0) {
//Randomly select a neighbor from this list
int index = random.nextInt(neighbors.size());
next = neighbors.get(index);
//Stack the current cell
stack.push(current);
//Remove the walls between the current maze cell and the randomly selected neighbor cell
this.removeWall(current,next);
//Mark the neighbor cell as visited and use it as the current cell
next.setVisited(true);
current = next;
//If an access is marked, the counter is decreased by 1
unVisitedCount--;
}
else if(stack.isEmpty() == false) {//If the current maze cell does not have an unreachable adjacent maze cell, and the stack is not empty
/*
1.The maze unit at the top of the stack comes out of the stack
2.Make it the current maze unit
*/
Block cell = stack.pop();
current = cell;
}
}
}
//Find neighbors as well as the getneighbors methods:
//Find out whether the current cell has an unreachable neighbor cell
public List<Block> findNeighbors() {
//The neighbors are divided into upper, lower, left and right
List<Block> res = new ArrayList<Block>();
Block top = this.getNeighbor(0,false);
Block right = this.getNeighbor(1,false);
Block bottom = this.getNeighbor(2,false);
Block left = this.getNeighbor(3,false);
if(top != null){
res.add(top);
}
if(right != null){
res.add(right);
}
if(bottom != null){
res.add(bottom);
}
if(left != null){
res.add(left);
}
return res;//Return neighbor array
}
//Get neighbors according to direction
public Block getNeighbor(int type,boolean lose_visited) {
Block neighbor;
int neighbor_i = 0, neighbor_j = 0;
switch(type) {
case 0:
neighbor_i = this.i-1;
neighbor_j = this.j;
break;
case 1:
neighbor_i = this.i;
neighbor_j = this.j+1;
break;
case 2:
neighbor_i = this.i+1;
neighbor_j = this.j;
break;
case 3:
neighbor_i = this.i;
neighbor_j = this.j-1;
break;
}
Block[][] blocks = panel.blocks;
//It's beyond the boundary, therefore no neighbor
if(neighbor_i < 0 || neighbor_j < 0 || neighbor_i >= panel.ROWS || neighbor_j >= panel.COLS) {
neighbor = null;
}
//The dimensions are permitted, neighbor is found
else {
//Find the neighbor, either top/bottom/left/right
neighbor = blocks[neighbor_i][neighbor_j];
//Judge whether it is accessed. If it is accessed, null is returned
if(neighbor.visited && !lose_visited) {//lose_visited equals true to ignore access
neighbor = null;
}
}
return neighbor;
}
要制作包含多个解决方案的迷宫,您需要移除将解决方案路径连接到 non-solution 路径的墙壁。然后将 non-solution 路径添加到备用解决方案。
您可能还想移除多个 non-solution 路径之间的一些墙,让它变得有趣。
留空区的问题比较有意思。如果是 4 向连接,您可以从一个单元格中移除所有 4 面墙,因此您需要检查相邻单元格是否有墙连接到角落。
然后问题是移除是否微不足道 - 连接是否靠近 2 条路径已经连接的点?
- 确定所有具有该连接的墙部分 属性,
- 并且不要导致琐碎的解决方案
- 检查移除该墙部分是否不会破坏拐角规则。
- 随机select一个
- 重复直到你有足够的替代解决方案。