是否有一种算法可以在棋盘游戏中找到所有可能的路线?
Is there an algorithm to find all possible routes in a board game?
我正在尝试编写一个 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 是一个包含棋盘数据的二维数组。自由空间、墙壁和可达空间分别用0s、1s和2s表示。
Here's an example of what is looks like given N=6
编辑:如下所述,我试图在 N 次或更少的移动中找到所有可到达的单元格。
您应该使用广度优先搜索来解决您的问题。您可以阅读有关 BFS here 的内容。下面是我在 Java 中未运行的代码。我建议不要使用它,因为我在 Whosebug 编辑器中对其进行了编码,但基本思想就在那里。
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;
}
}
就像其他人写的那样,您应该使用广度优先遍历而不是深度优先遍历。
其次,您不应重新访问已标记为值 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"));
我正在尝试编写一个 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 是一个包含棋盘数据的二维数组。自由空间、墙壁和可达空间分别用0s、1s和2s表示。
Here's an example of what is looks like given N=6
编辑:如下所述,我试图在 N 次或更少的移动中找到所有可到达的单元格。
您应该使用广度优先搜索来解决您的问题。您可以阅读有关 BFS here 的内容。下面是我在 Java 中未运行的代码。我建议不要使用它,因为我在 Whosebug 编辑器中对其进行了编码,但基本思想就在那里。
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;
}
}
就像其他人写的那样,您应该使用广度优先遍历而不是深度优先遍历。
其次,您不应重新访问已标记为值 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"));