使用递归来解决java中的迷宫

时间:2016-07-29 01:13:17

标签: java recursion maze

我尝试了这个问题,并且由于某些原因它不正确。给定一个字符串数组,找出迷宫中存在多少可能的解决方案,其中字符串由一个" R" (老鼠),一个" C" (奶酪),多个" X(无法通过的块)和"。""(可能的途径)。任务是找到大鼠可以采取的可能路线的数量,以获得奶酪,而不会增加其自身与奶酪在其路径上的任何点之间的(欧几里得)距离。我的代码出了什么问题?

public class RatRoute { 
private static String[] enc;
private static int count;
private static int[] r;
private static int[] c;

// Test the program
public static void main(String[] args) {
    String[] test = {
            ".R...",
            "..X..",
            "....X",
            "X.X.X",
            "...C."};
    int num1 = numRoutes(test);
    System.out.println(num1);   
}

// Set variables, and call recursive function
public static int numRoutes(String[] enc) {
    RatRoute.enc = enc;     
    r = findR(enc);
    c = findC(enc);
    recursiveHelper(r[0], r[1]);
    return count;
}

// Recursive 
public static void recursiveHelper(int x, int y) {

    /*System.out.println();
    System.out.println();
    for (int k = 0; k < enc.length; k++) {
        System.out.println(enc[k]);
    }*/

    if(isBlock(x,y)) {
        return;
    } else if (isBigger(x,y)) {
        return;
    } else if (isCheese(x, y)) {
        count++;
        //System.out.println("Found the Cheese! Path number: " + count);
        //System.out.println();
        return;
    }

    enc[x] = currentPath(x,y);      
    recursiveHelper(x + 1, y);
    recursiveHelper(x, y + 1);
    recursiveHelper(x, y - 1);
    recursiveHelper(x - 1, y);
    enc[x] = returnPath(x,y);

}

// Change the most recently traveled coordinates into a block 
public static String currentPath(int x, int y) {
    char[] Chars = enc[x].toCharArray();
    Chars[y] = 'X';
    String newString = String.valueOf(Chars);
    return newString;       
}

// Turn path already traveled from blocks back into a usable path to travel (undo the currentPath method)
public static String returnPath(int x, int y) {
    char[] Chars = enc[x].toCharArray();
    Chars[y] = '.';
    String newString = String.valueOf(Chars);
    return newString;       
}

// Check if the next movement is into the cheese
public static boolean isCheese(int x, int y) {
    if (enc[x].charAt(y) == 'C') {
        return true;
    } else {
        return false;
    }
}

// Check if the next movement is into a block, or outside the given array
public static boolean isBlock(int x, int y) {   
    if (x == -1 || y == -1
            || x >= enc.length || y >= enc[x].length()) {
        return true;
    } else if (enc[x].charAt(y) == 'X') {
        //System.out.println(x + "," + y);
        return true;
    } else {
        return false;
    }
}

// See if the distance between the rat and the cheese has gotten larger or smaller
public static boolean isBigger(int x, int y) {
    double rx = r[0]; double ry = r[1];
    double cx = c[0]; double cy = c[1];

    double originalDist = Math.sqrt(Math.pow(rx-cx, 2) + Math.pow(ry-cy, 2));
    double newDist = Math.sqrt(Math.pow(x-cx, 2) + Math.pow(y-cy, 2));

    //System.out.println("Orginal Distance: " + originalDist);
    //System.out.println("New Distance: " + newDist);

    if (newDist > originalDist) {
        return true;
    } else {
        return false;
    }
}

// Find the variables for the original position of the rat
public static int[] findR(String[] enc) {
    for (int i = 0; i < enc.length; i++) {
        for (int j = 0; j < enc[i].length(); j++) {
            if (enc[i].charAt(j) == 'R') {
                int[] coordinates = {i, j};
                //System.out.println(coordinates[0] + "," + coordinates[1]);
                return coordinates;                 
            } else {

            }
        }
    }
    int[] other = {-1, -1};
    return other;
}

// Find the variables for the original position of the rat
public static int[] findC(String[] enc) {
    for (int i = 0; i < enc.length; i++) {
        for (int j = 0; j < enc[i].length(); j++) {
            if (enc[i].charAt(j) == 'C') {
                int[] coordinates = {i, j};
                //System.out.println(coordinates[0] + "," + coordinates[1]);
                return coordinates;                 
            } else {

            }
        }
    }
    int[] other = {-1, -1};
    return other;
}

}

1 个答案:

答案 0 :(得分:0)

让我们从一个有用的观察开始:

  

[...]没有增加它与自身之间的(欧几里得)距离   奶酪在其路径上的任何一点。

基本上它意味着每当老鼠靠近奶酪时,它就永远不会回到更远的位置。

所以让我们说大鼠 x 坐标是3而奶酪 x 坐标是5,老鼠不能“左转”(即x = 2),因为这会使它比形成奶酪前更远。

因此,简单问题的一个好方法是找到老鼠可以去的方向。在你的例子中,老鼠从奶酪上方左上方,所以它只能向下或向右移动,否则它会越来越远离奶酪。当大鼠 x 与奶酪 x 匹配时,它将无法向右或向左移动, y 也是如此。

使用您的代码,如果:

r[0] - c[0] = 0 // the rat cannot move on the x any more.
r[1] - c[1] = 0 // the rat cannot move on the y any more.

r[0] - c[0] == 0 && r[1] - c[1] == 0

老鼠到了奶酪!在这种情况下,我们可以增加计数器,因为找到了成功的路线。

现在让我们通过递归来实现这一点。 从您发布的代码开始,我们从给定的c(与findC(enc)找到)和给定的r开始(与findR(enc)找到)

所以递归方法看起来像这样:

private void findRoutesFrom(int[] r) {
    // what directions can the rat go?
    // if the cheese is on the right of the mouse, xDirection
    // would be +1.
    int xDirection = (int) Math.signum(c[0] - r[0]);
    // if the cheese is below of the mouse, yDirection
    // would be +1.
    int yDirection = (int) Math.signum(c[1] - r[1]);

    // Now, if xDirection is != 0 the rat can attempt to move
    // in that direction, checking if there's not a block
    if(xDirection != 0 && !isBlock(r[0] + xDirection, r[1])) {
        // if it can move in that direction, then use recursion to
        // find all the possible paths form the new position
        findRoutesFrom(new int[]{r[0] + xDirection, r[1]});
    }

    // same goes for yDirection
    if(yDirection != 0 && !isBlock(r[0], r[1] + yDirection)) {
        findRoutesFrom(new int[]{r[0], r[1] + yDirection});
    }

    // if the rat reaches the cheese, increase the successful
    // paths counter
    if(xDirection == 0 && yDirection == 0) {
        count++;
    }
}

就是这样!由于Eculedean距离约束,检查方向是否为!= 0就足够了,因为当它是假的时候,那么老鼠就不能再朝这个方向移动了。