有没有一种算法可以找到棋盘游戏中所有可能的路径?

3
我尝试编写一个javascript函数,在一个15x15的棋盘上找出长度为N的所有可能路径,其中玩家不能对角线移动。我能够想出一个相当简单的递归解决方案,但我怀疑它极不优化。
以下是代码:
search(n, u, v) {

    if (n == 0 || isWall(u, v))
        return;
        
    board[v][u] = 2;
    
    search(n - 1, u, v - 1);
    search(n - 1, u + 1, v);
    search(n - 1, u, v + 1);
    search(n - 1, u - 1, v);
    
    return;
}

board 是一个二维数组,包含了棋盘的数据。空白格、墙壁和可到达的空间分别由0、1和2表示。

这是一个给定N=6的例子

SampleBoard

编辑:正如下面所提到的,我正在尝试找到所有在N个或更少的移动步数内可以到达的单元格。


从技术上讲,你在这里写的并不是“找到所有长度为N的可能路径”,而是“在N步或更少的步数内到达的所有可到达单元格”,这要容易得多。你真正想要哪一个? - RBarryYoung
是的,可以找到所有路线,但通常迭代次数太多。可以计算路线或显示在n步内可达到哪些位置。 - Christian Sloper
https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm - meriton
对于每个可达的单元格,你可以使用A*搜索算法找到通往该单元格的最短路径。这将为您提供到每个单元格的路线,但并非所有路线。这样是否足够? - marathon
2个回答

2

像其他人写的一样,你应该使用广度优先遍历而不是深度优先遍历。

其次,你不应该重新访问已经标记为值2的单元格,所以你应该继续的条件应该是当前单元格具有值0。

我建议使用两个数组来实现遍历:

function search(board, n, u, v) {
    let count = 0;
    let frontier = [[u, v]];
    
    while (n-- > 0 && frontier.length) {
        let newFrontier = [];
        for (let [u, v] of frontier) {
            if (board[v]?.[u] === 0) {
                board[v][u] = 2;
                count++;
                newFrontier.push([u, v - 1], [u + 1, v], [u, v + 1], [u - 1, v]);
            }
        }
        frontier = newFrontier;
    }
    
    return count;
}

let board = [
    "11111111111111",
    "10000000000001",
    "10000000000001",
    "10011100111001",
    "10010000001001",
    "10010000001001",
    "10000000000001",
    "10000000000001",
    "10000000000001",
    "10010000001001",
    "10010000001001",
    "10011100111001",
    "10000000000001",
    "10000000000001",
    "11111111111111"
].map(row => Array.from(row, Number));

let res = search(board, 6, 2, 2);

console.log("number of cells reached: ", res);

console.log(board.map(row => row.join(" ")).join("\n"));


1

你应该使用广度优先搜索算法来解决问题。你可以在这里了解有关BFS的内容。以下是我未运行的Java代码。我建议不要使用这个,因为我是在StackOverflow编辑器中编写的,但基本思路已经在那里了。

public class BFS {
    static final int MAX_N = 100;
    public static void main(String[] args) {
         int[][] board = new int[MAX_N][MAX_N];
         Queue<Point> q = new LinkedList<>();
         List<int[]> reachable = new ArrayList<>();
         boolean[][] vist = new boolean[MAX_N][MAX_N];
         q.add(new Point(0,0,0));
         vist[0][0] = true;
         while(!q.isEmpty()) {
             Point curr = q.poll();

             if(vist[curr.x][curr.y]) continue;
             if(curr.move > N) continue;
 
             reachable.add(new int[]{curr.x, curr.y});

             // dx and dy array not shown
             for(int i = 0; i < 4; i++) {
                 int nx = curr.x + dx[i];
                 int ny = curr.y + dy[i];

                 if(nx < 0 || nx >= MAX_N || ny < 0 || ny >= MAX_N) continue;
                 if(board[nx][ny] == 1) continue;

                 vist[nx][ny] = true;
                 q.add(new Point(nx, ny, curr.move+1));
                 
             }
         }

         // You now have your reachable points.
    }
}

class Point {
    public int x, y, move;
    public Point(int x, int y, int move) {
        this.x = x;
        this.y = y;
        this.move = move;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接