首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >N皇后问题解的验证

N皇后问题解的验证
EN

Stack Overflow用户
提问于 2018-12-03 07:51:46
回答 2查看 1.2K关注 0票数 0

我正在尝试编写一个函数,它得到一个MxN大小的板,其中有一列和一行,其中放置了皇后。然后我想看看女王是否受到了威胁。通常情况下,我会取这一行,并检查它的任何其他皇后,同样的列和对角线使用的循环。然而,这里有一个微小的变化,在板上也有墙可以保护女王的安全,即使在同一排中还有一个:

代码语言:javascript
复制
* * Q X * Q
* * X * * *
* Q X X Q *
Q * X Q Q *

其中Q是皇后,X是墙,*是空瓷砖。在0,2的位置上的女王没有受到威胁,即使在那一排中还有一个。

另外,整个板被保存在一个2d数组中,其中皇后被赋予1的int值,墙壁是-1,空格是0。

我的想法是翻过整排,如果某个地方有女王,那么我应该找一堵墙,从那个位置一直到我正在看的皇后,再找一堵墙。不过,在我的女王之后还有第二部分。

我试着想做个总结,但那也不太管用。有人对如何实现这一点有任何想法吗?(如果威胁返回true;如果不受威胁返回false;)

编辑:这是我的代码

代码语言:javascript
复制
`public static boolean isQueenThreatened(int[][] board, int row, int col){
        boolean safe=true; 
        for(int j = 0; j < col & safe ; j++){
            if(board[row][j]==1) {
                for (int i = j+1 ; i<col ; i++ ) {
                        if(board[row][i]!=-1) safe = false;
                }
            }
        }
        for(int j = col+1; j < board[row].length & safe ; j++){
            if(board[row][j]==1) {
                for (int i = j+1 ; i<board[row].length ; i++ ) {
                    if(board[row][i]!=-1) safe = false;
                }
            }

        }
        return safe;
    }`

所以这个函数得到了女王的位置(假设它是有效的),然后我想检查这一行,直到我的皇后,然后在它之后,看看是否有其他的皇后,如果有,我想检查它们之间是否有墙来保护我的女王,显然我的没有工作,因为如果他们之间除了一堵墙之外,它会产生假的,这就足够了,只有一堵墙,它不一定是所有的墙。

代码语言:javascript
复制
* Q * * X Q' * X Q

我用‘表示我的女王,我的代码将返回假的那个例子,即使它应该是真的..然后我必须对对角线和列做同样的操作。这是我需要帮助的地方。

EN

回答 2

Stack Overflow用户

发布于 2018-12-03 09:10:53

这是一个使用Iterator的绝佳机会。

代码语言:javascript
复制
static class Board {
    private final int width;
    private final int height;
    private final int[][] board;
    private static final int EMPTY = 0;
    private static final int WALL = -1;
    private static final int QUEEN = 1;


    public Board(int width, int height) {
        this.width = width;
        this.height = height;
        board = new int[height][width];
    }

    public Board(String[] setup) {
        this(setup[0].length(), setup.length);
        for (int y = 0; y < setup.length; y++) {
            for (int x = 0; x < setup[y].length(); x++) {
                switch (setup[y].charAt(x)) {
                    case '*':
                        board[y][x] = EMPTY;
                        break;
                    case 'X':
                        board[y][x] = WALL;
                        break;
                    case 'Q':
                        board[y][x] = QUEEN;
                        break;
                }
            }
        }
    }

    public Iterator<Integer> walk(int xStart, int yStart, int dx, int dy) {
        return new Iterator<Integer>() {
            int x = xStart;
            int y = yStart;

            @Override
            public boolean hasNext() {
                return x + dx < width && y + dy < height
                        && x + dx >= 0 && y + dy >= 0;
            }

            @Override
            public Integer next() {
                return board[y += dy][x += dx];
            }
        };
    }

    public int get(int x, int y) {
        return board[y][x];
    }
}

enum Direction {
    NORTH(0, -1),
    NORTH_WEST(1, -1),
    WEST(1, 0),
    SOUTH_WEST(1, 1),
    SOUTH(0, 1),
    SOUTH_EAST(-1, 1),
    EAST(-1, 0),
    NORTH_EAST(-1, -1),
    ;
    private final int dx;
    private final int dy;

    Direction(int dx, int dy) {
        this.dx = dx;
        this.dy = dy;
    }
}

public static boolean isQueenThreatened(Board board, int row, int col) {
    for (Direction direction : Direction.values()) {
        walk: for (Iterator<Integer> attack = board.walk(col, row, direction.dx, direction.dy); attack.hasNext(); ) {
            switch (attack.next()) {
                case Board.QUEEN:
                    return true;
                case Board.WALL:
                    break walk;
            }
        }
    }
    return false;
}

private void test() {
    String[] test = new String[]{
            "**QX*Q",
            "**X***",
            "*QXXQ*",
            "Q*XQQ*"
    };
    Board board = new Board(test);
    for (int y = 0; y < board.height; y++) {
        for (int x = 0; x < board.width; x++) {
            if (board.get(x, y) == Board.QUEEN) {
                System.out.println("Queen at position (" + x + "," + y + ") is " + (isQueenThreatened(board, y, x) ? "" : "NOT") + " threatened");
            }
        }

    }
}

顺便说一句,您在(0,2) 的女王在(2,4)受到了女王的威胁。

票数 1
EN

Stack Overflow用户

发布于 2018-12-03 08:21:08

对于给定的皇后位置,您需要迭代行、列和每个对角线。在每个方向上,您都可以遵循相同的规则:

  1. 如果你打了另一个女王,你会受到威胁,还true
  2. 如果你撞到墙上,你在那个方向上是安全的,继续下一个检查。
  3. 如果你击中了板的边缘,你在这个方向上是安全的,继续下一个检查。
代码语言:javascript
复制
public static boolean isQueenThreatened(int[][] board, int row, int col) {
    // Go over the row, to the left:
    for (int i = col - 1; i >= 0; --i) {
        int val = board[row][i];
        if (val == 1) {
            return true;
        }
        if (val == -1) {
            break;
        }
    }

    // Same logic for:
    // - Going over the row to the right
    // - Going over the column to the top
    // - Going over the column to the bottom
    // - Going over the top left diagonal
    // - Going over the top right diagonal
    // - Going over the bottom left diagonal
    // - Going over the bottom right diagonal

    // If you reached here, it means that no early return was performed,
    // and the queen is safe
    return false;
}

编辑:

为了满足注释中的要求,您可以添加额外的boolean来查找撞墙威胁,但我认为代码看起来要糟糕得多:

代码语言:javascript
复制
public static boolean isQueenThreatened(int[][] board, int row, int col) {
    boolean threat = false;

    // Go over the row, to the left:
    boolean wall = false;
    for (int i = col - 1; i >= 0 && !threat && !wall; --i) {
        int val = board[row][i];
        if (val == 1) {
            threat = true;
        }
        if (val == -1) {
            wall = true;
        }
    }

    // Go over the row, to the right.
    // Reset the wall variable, as you haven't detected a wall in this direction yet
    // The threat potentially found in the previous loop is still present
    // so if it still exists, the loop will be skipped 
    boolean wall = false;
    for (int i = col + 1; i < board[row].length && !threat && !wall; ++i) {
        int val = board[row][i];
        if (val == 1) {
            threat = true;
        }
        if (val == -1) {
            wall = true;
        }
    }

    // Same logic for:
    // - Going over the column to the top
    // - Going over the column to the bottom
    // - Going over the top left diagonal
    // - Going over the top right diagonal
    // - Going over the bottom left diagonal
    // - Going over the bottom right diagonal

    // If you reached here, it means that no early return was performed,
    // and the queen is safe
    return threat;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53589529

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档