8-Queen解决方案Java代码的说明。

时间:2015-07-14 06:48:15

标签: java backtracking n-queens

我找到了一个8-Queen解决方案,我能够在Eclipse中编译和运行。我相信这个解决方案遵循回溯方法,并且工作的重点在solutionunsafe函数中完成,但我很难理解其中的代码路径。有人可以帮我理解这段代码的作用。

我的来源 - http://rosettacode.org/wiki/N-queens_problem#Java 我根据其他来源发布的92个解决方案验证了输出。看起来不错。所以我知道代码有效。

我试图对其进行格式化并添加一些基本注释以便清理 -

private static int[] b = new int[8];
private static int s = 0;

public static void main(String[] args) {
    // solution from - http://rosettacode.org/wiki/N-queens_problem#Java
    new QueenN();
}

public QueenN() {
    solution();
}

public void solution() {
    int y = 0;
    b[0] = -1;
    while (y >= 0) {
        do {
            b[y]++;
        } while ((b[y] < 8) && unsafe(y));

        if (b[y] < 8) {

            if (y < 7) {
                b[++y] = -1;
            } else {
                putboard();
            }

        } else {
            y--;
        }
    }
}

// check if queen placement clashes with other queens
public static boolean unsafe(int y) {
    int x = b[y];
    for (int i = 1; i <= y; i++) {
        int t = b[y - i];
        if (t == x || t == x - i || t == x + i) {
            return true;
        }
    }
    return false;
}

// printing solution
public static void putboard() {
    System.out.println("\n\nSolution " + (++s));
    for (int y = 0; y < 8; y++) {
        for (int x = 0; x < 8; x++) {
            if (b[y] == x)
                System.out.print("|Q");
            else
                System.out.print("|_");
        }
        System.out.println("|");
    }
}

结束。

1 个答案:

答案 0 :(得分:1)

让我们尝试逐步理解代码。首先,我们调用函数solution(),这是导致拼图答案执行的原因。

解决方案功能:

public void solution() {
    int y = 0;
    b[0] = -1;
    while (y >= 0) {
        do {
            b[y]++; //if last cell was unsafe or we reached the end of the board, we go for the next row.
        } while ((b[y] < 8) && unsafe(y)); //Checks whether it's the last cell and if it's an unsafe cell (clashing)

        if (b[y] < 8) { //We found a safe cell. Hooray!

            if (y < 7) { //Did we place the last queen?
                b[++y] = -1; //Nope, let's allocate the next one.
            } else {
                putboard(); //Yup, let's print the result!
            }

        } else { //If not a single safe cell was found, we reallocate the last queen.
            y--;
        }
    }
}

第一次,您将连续遍历每个单元格(或列,但您更喜欢它。它只是一个旋转问题)。在每个单元格上,您进行不安全(y)检查,如果您放置女王的单元格与其他女王占用的单元格发生冲突,则返回true(正如您在评论中已经发现的那样) )。

下一步,一旦我们找到了一个放置实际女王(y)的安全单元格,我们会进行安全检查:如果我们没有为该女王找到一个安全单元,我们必须重新分配最后一位女王。

如果发现细胞并且是正确的,我们检查它是否是最后一个女王(y <7)。如果是这样,我们继续打印结果。否则,我们只需通过放置b [++ y] = -1。

重新启动while循环

不安全的功能:

public static boolean unsafe(int y) {
    int x = b[y]; //Let's call the actual cell "x"
    for (int i = 1; i <= y; i++) { //For each queen before placed BEFORE the actual one, we gotta check if it's in the same row, column or diagonal.
        int t = b[y - i];
        if (t == x || t == x - i || t == x + i) {
            return true; //Uh oh, clash!
        }
    }
    return false; //Yay, no clashes!
}

此功能检查女王是否在此之前与任何已分配的女王发生冲突。冲突可能发生在对角线,垂直或水平方向:这就是为什么在&#34;返回true&#34;之前会有三重OR检查。言。

Putboard功能:

public static void putboard() {
    System.out.println("\n\nSolution " + (++s));
    for (int y = 0; y < 8; y++) {
        for (int x = 0; x < 8; x++) {
            if (b[y] == x)
                System.out.print("|Q");
            else
                System.out.print("|_");
        }
        System.out.println("|");
    }
}

我不会那么深刻地解释这个,因为它只是一个相当简单的行打印功能,你可以在执行解决方案时自己找出它是如何工作的!

希望这有帮助。

干杯!