使用Graph和DFS,Knight's Java in Java(递归)

时间:2016-01-13 13:37:21

标签: java recursion graph depth-first-search bag

我正在尝试计算5x5场上所有可能的骑士动作:

为此,我尝试使用DFS(深度优先搜索)类和Graph类。

我认为在这篇文章中粘贴这些整个类可能是太多代码(可能不够相关),所以我在这里显示它们:

Graph.java

DepthFirstSearch.java

Graph.java使用Bag.java:

Bag.java

该字段看起来像这样(使用每个字段的id):

0  1  2  3  4
5  6  7  8  9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24

在CalculatePath方法中使用以下属性,该方法应计算骑士可以从特定方格中访问每个方格一次的可能巡回量(应该花费一两分钟来解决)。

可能的骑士步骤(在主类中)被定义(使用图形的边缘,G):

G.addEdge(0, 11);
G.addEdge(0, 7);

G.addEdge(1, 8);
G.addEdge(1, 10);
G.addEdge(1, 12);

G.addEdge(2, 5);
G.addEdge(2, 9);
G.addEdge(2, 11);
G.addEdge(2, 13);

G.addEdge(3, 6);
G.addEdge(3, 12);
G.addEdge(3, 14);

G.addEdge(4, 7);
G.addEdge(4, 13);

G.addEdge(5, 2);
G.addEdge(5, 12);
G.addEdge(5, 16);

G.addEdge(6, 15);
G.addEdge(6, 17);
G.addEdge(6, 3);
G.addEdge(6, 13);

G.addEdge(7, 0);
G.addEdge(7, 4);
G.addEdge(7, 10);
G.addEdge(7, 14);
G.addEdge(7, 16);
G.addEdge(7, 18);

G.addEdge(8, 1);
G.addEdge(8, 17);
G.addEdge(8, 19);
G.addEdge(8, 11);

G.addEdge(9, 2);
G.addEdge(9, 12);
G.addEdge(9, 18);

G.addEdge(10, 1);
G.addEdge(10, 21);
G.addEdge(10, 7);
G.addEdge(10, 17);

G.addEdge(11, 0);
G.addEdge(11, 2);
G.addEdge(11, 20);
G.addEdge(11, 22);
G.addEdge(11, 8);
G.addEdge(11, 18);

G.addEdge(12, 1);
G.addEdge(12, 3);
G.addEdge(12, 21);
G.addEdge(12, 23);
G.addEdge(12, 5);
G.addEdge(12, 9);
G.addEdge(12, 15);
G.addEdge(12, 19);

G.addEdge(13, 2);
G.addEdge(13, 4);
G.addEdge(13, 22);
G.addEdge(13, 24);
G.addEdge(13, 6);
G.addEdge(13, 16);

G.addEdge(14, 3);
G.addEdge(14, 23);
G.addEdge(14, 7);
G.addEdge(14, 17);

G.addEdge(15, 6);
G.addEdge(15, 12);
G.addEdge(15, 22);

G.addEdge(16, 5);
G.addEdge(16, 7);
G.addEdge(16, 13);
G.addEdge(16, 23);

G.addEdge(17, 6);
G.addEdge(17, 8);
G.addEdge(17, 10);
G.addEdge(17, 14);
G.addEdge(17, 20);
G.addEdge(17, 24);

G.addEdge(18, 7);
G.addEdge(18, 9);
G.addEdge(18, 11);
G.addEdge(18, 21);

G.addEdge(19, 8);
G.addEdge(19, 12);
G.addEdge(19, 22);

G.addEdge(20, 11);
G.addEdge(20, 17);

G.addEdge(21, 10);
G.addEdge(21, 12);
G.addEdge(21, 18);

G.addEdge(22, 11);
G.addEdge(22, 13);
G.addEdge(22, 15);
G.addEdge(22, 19);

G.addEdge(23, 12);
G.addEdge(23, 14);
G.addEdge(23, 16);

G.addEdge(24, 13);
G.addEdge(24, 17);

int currentSquare = 20;
calculatePath(currentSquare);
System.out.println("From square " + currentSquare + " there are " + tours + " possible tours.");

以下是我试图找到可能的旅程:

  private static void calculatePath(int currentSquare) {
        boolean foundChoice = false;
        for (int point : G.adj(currentSquare)) {

            if (dfs.marked(currentSquare)) {
                foundChoice = true;
//              dfs.unmark(currentSquare);
                calculatePath(point);
            }
        }
        if (!foundChoice) {
            tours++;
            dfs.unmark(currentSquare);
        }
        System.out.println(currentSquare + " - tours: " + tours);
    }

例如,如果我尝试通过calculatePath(20)调用此递归函数,它应该使用该字段上的每个正方形从该正方形返回所有可能的游览(tours)。

未标记的正方形是已经到达的正方形,不应再在同一个游览中可访问。

现在,问题是我无法让CalculatePath跳过已经访问过的方块(输出显示它从20到17,从20到11,然后停止递归方法)。

此外,该方法还不计算多个游览。我想首先正确计算一条路径并最终计算所有可能的游览。

我正在使用的所有代码都是在这篇文章中提供的 - 包括上面链接中的类。

1 个答案:

答案 0 :(得分:1)

仍然:)此代码存在许多问题,但看起来您正在取得进展。

您的方法DepthFirstSearch.marked对我来说似乎不对。我认为如果它成功地将标记从true更改为false,它应该返回true。在这里,您只返回marked[w]的值。

您的DepthFirstSearch构造函数似乎正在尝试标记所有相邻(及其所有相邻点)。这看起来很奇怪 - 你怎么期望这个工作?避免循环的正常DFS机制是在递归完成时递归并移除标记时在您触摸的每个位置留下标记。在这里,您似乎在开始时标记所有正方形,然后在您完成所有邻接的一轮而未找到标记的正方形时取消标记它们。