迷宫解决程序

时间:2017-12-02 06:13:54

标签: java recursion infinite-recursion

目前我正在尝试解决一个确定是否可以解决迷宫的程序,如果迷宫是可解决的,它应该打印出通过迷宫路径的步数。起始位置和结束位置以及迷宫在输入文件中以下列格式给出:

第1行:测试用例(N)

对于每N行,第一行将包含迷宫的大小,将给出起始位置和结束出口位置。然后,迷宫的视觉描绘也将出现在输入文件

例如,此挑战的示例输入是:

3
6 7 0 0 5 6
1110111
1011101
1001001
1011101
1000001
1111110
3 3 2 0 0 2
111
110
111
5 5 1 0 3 1
01111
11001
01001
01001
01111

迷宫的精确规则是0是不可穿透的墙壁,1s是能够四处移动的自由行走空间。最终位置也没有任何特殊字符标记,而是给我们提供位置。

以下代码是我接受挑战的方法,显然不起作用:

import java.io.*;
import java.util.*;
public class Maze
{

    public static void main(String[] args) throws FileNotFoundException
    {
        Scanner sc = new Scanner(new File("maze.txt"));
        int tc = sc.nextInt();
        for(int p  = 0; p < tc; p++ ) {
            int rows = sc.nextInt();
            int cols = sc.nextInt();
            int startRow = sc.nextInt();
            int startCol = sc.nextInt();
            int endRow = sc.nextInt();
            int endCol = sc.nextInt();
            sc.nextLine();
            char[][] maze = new char[rows][cols];
            for(int i = 0; i < rows; i++) {
                String s = sc.nextLine();
                for(int j = 0; j < cols; j++) {
                    maze[i][j] = s.charAt(j);
                }
            }

            if(solvable(maze,startRow,startCol,endCol,endRow)) {
                int count = 0;
                for(char[] arr : maze) {
                    for(char elem: arr) {
                        if(elem == 'x') count++;
                    }
                }
                System.out.println("It takes " + count + " steps to solve the maze");
            }else {
                System.out.println("Unsolvable");
            }


        }

    }


    public static boolean solvable(char[][] maze,int row, int col,int finishRow, int finishCol) {

        if(row < 0 || col < 0 || row >maze.length - 1 || col > maze[0].length - 1) {
            return false;
        }
        if(row == finishRow && col == finishCol) {
            return true;
        }
        if(maze[row][col] == 0) {
            return false;
        }
        char c = maze[row][col];
        maze[row][col] = 'x';
        if(solvable(maze,row + 1,col,finishRow,finishCol)) {
            return true;
        }
        if(solvable(maze,row - 1,col,finishRow,finishCol)){
            return true;
        }
        if(solvable(maze,row ,col + 1,finishRow,finishCol)) {
            return true;
        }
        if(solvable(maze,row,col - 1,finishRow,finishCol)) {
            return true;
        }
        maze[row][col] = c;
        return false;


    }

}

正如标题所示,该程序产生堆栈溢出错误。我正在整合解决迷宫的一般算法,而不是纳入洪水填充算法。我需要在我的递归方法中找出可解决的缺陷。请注意,这是一个竞争性的编程环境,因此从java的面向对象方面编码将是不方便的。

1 个答案:

答案 0 :(得分:0)

问题是solvable中的无限递归。这是为什么? 为什么它永远不会终止? 让我们仔细看看它是如何工作的:

    如果职位无效,则
  • return false
  • 如果职位是目标,则
  • return true
  • return false如果位置是开始
    • 这有点奇怪,但无论如何,让我们继续前进
  • 此时我们知道当前位置有效
  • 保存当前位置的旧值,并使用'x'
  • 进行标记
  • 尽量向所有方向移动
  • 恢复当前位置的原始值

这个逻辑中的缺陷在哪里?

何时使用标记'x'? - &GT;哈!

如果没有使用标记'x',会发生什么? - &GT;哈!

想象一下这就是迷宫,算法总是在检查其他方向之前先检查下行路径:

#####
#S E#
# ###
# ###
#####

算法首先从S到底部。 在底部有一种方法可以上升, 所以它迈出了一步。 在那里,有一种方式可以下降,所以它会回落。 它会一直上下停滞不前。

所以解决方案是使用'x'标记来避免永远探索相同的位置。