Java中具有一维数组的N皇后难题

Java中具有一维数组的N皇后难题,java,arrays,n-queens,Java,Arrays,N Queens,我正在研究一个在初学者中似乎有点有名的问题,8皇后之谜。我见过一些使用2D数组、递归等来解决这个问题的方法,但这个问题是CS课程书中介绍1D数组一章中给出的作业,因此解决这个问题的可用技术是有限的 我使用的过程是首先创建一个大小为64的1D数组,这样就可以放置索引0到63之间的皇后。然后生成一个随机位置索引,并进行测试以检查是否有任何皇后攻击该位置。如果此位置未受到任何皇后的攻击,则通过设置板[position]=true放置皇后。放置皇后后,queenCount将递增,此过程将重复,直到放置了

我正在研究一个在初学者中似乎有点有名的问题,8皇后之谜。我见过一些使用2D数组、递归等来解决这个问题的方法,但这个问题是CS课程书中介绍1D数组一章中给出的作业,因此解决这个问题的可用技术是有限的

我使用的过程是首先创建一个大小为64的1D数组,这样就可以放置索引0到63之间的皇后。然后生成一个随机位置索引,并进行测试以检查是否有任何皇后攻击该位置。如果此位置未受到任何皇后的攻击,则通过设置
板[position]=true
放置皇后。放置皇后后,
queenCount
将递增,此过程将重复,直到放置了8个皇后

如果皇后的放置方式无法放置8,则电路板在1毫秒后通过执行时间检查重置,并重试放置8个皇后。我最多只能放置7个皇后,但最后一个皇后从未放置过。每次尝试都会打印出来,同时打印此尝试的
queenCount
。是否有可能使用这种方法,或者这是一条死胡同

代码示例如下:

package ch7;

public class Chapter_07_E22_EightQueens64bool {

    public static void main(String[] args) {

        int queenCount = 0;
        int attemptCount = 0;
        boolean[] board = new boolean[8 * 8];
        final long TIME_LIMIT = 1; //Milliseconds

        long startTime = System.currentTimeMillis();
        while (queenCount < 8) {

                int position = placeQueen(board.length);

                if(checkPosition(position, board) && !board[position]) {
                    board[position] = true;
                    queenCount++;
                }

                long timeCheck = System.currentTimeMillis();
                if (timeCheck - startTime > TIME_LIMIT) {
                    clearBoard(board);
                    queenCount = 0;
                    startTime = System.currentTimeMillis();
                }         
            System.out.println("Attempt #" + ++attemptCount);
            System.out.println(queenCount + " queens placed.");
            printBoard(board);
        }   
    }      

    public static void printBoard(boolean[] board) {

        for (int i = 0; i < board.length; i++) {

            if (board[i])
                System.out.print("|Q");
            else
                System.out.print("| ");

            if ((i + 1) % 8 == 0)
                System.out.println("|");    
        }
    }

    public static int placeQueen(int boardSize) {
        return (int)(Math.random() * boardSize);
    } 

    public static boolean[] clearBoard(boolean[] board) {

        for (int i = 0; i < board.length; i++)
            board[i] = false;

        return board;

    }

    public static boolean checkPosition(int position, boolean[] board) {

        return checkTop(position, board) && checkBottom(position, board) && checkLeft(position, board) &&
               checkRight(position, board) && checkTopLeft(position, board) && checkTopRight(position, board) &&
               checkBottomLeft(position, board) && checkBottomRight(position, board);
    }

    public static boolean checkTop(int position, boolean[] board) {
        // Checks each field above the current position while i >= 8  
        for (int i = position; i >= 8; i -= 8) {
            if (board[i - 8])
                    return false;  
        }
        return true;                
    }

    public static boolean checkBottom(int position, boolean[] board) {
        // Checks each field below the current position while i <= 55;
        for (int i = position; i <= 55; i += 8) {
            if (board[i + 8])
                    return false;
        }
        return true;                
    }

    public static boolean checkRight(int position, boolean[] board) {
        // Checks each field to the right of the current position while i % 8 < 7
        for (int i = position; i % 8 < 7; i += 1) {
            if (board[i + 1])
                return false;

        }
        return true;                
    }

    public static boolean checkLeft(int position, boolean[] board) {
        // Checks each field to the left of the current position while i % 8 != 0
        for (int i = position; i % 8 != 0; i -= 1) {
            if (board[i - 1])
                return false;  
        }
        return true;                
    }

    public static boolean checkTopLeft(int position, boolean[] board) {
        // Checks each field top left of the current position while i >= 9
        for (int i = position; i >= 9; i -= 9) {
            if (board[i - 9])
                return false;   
        }
        return true;                
    }

    public static boolean checkTopRight(int position, boolean[] board) {
        // Checks each field top right of the current position while i >= 7   
        for (int i = position; i >= 7; i -= 7) {
            if (board[i - 7])
                return false;   
        }
        return true;                
    }

    public static boolean checkBottomRight(int position, boolean[] board) {
        // Checks each field below the current position while i <= 54
        for (int i = position; i <= 54; i += 9) {
            if (board[i + 9])
                return false;    
        }
        return true;                
    }

    public static boolean checkBottomLeft(int position, boolean[] board) {
        // Checks each field below the current position while i <= 56
        for (int i = position; i <= 56; i += 7) {
            if (board[i + 7])
                return false;   
        }
        return true;                
    }

}
package ch7;

public class Chapter_07_E22_EightQueens {

    static final int N = 8;

    public static void main(String[] args) {

        int[] queens = new int[N];
        int attempts = 0;

        for (int i = 0; i < N; i++) 
            queens[i] = i;

        while (checkBoardForCollision(queens)) {
            shuffleBoard(queens);
            attempts++;
        }
        printBoard(queens);
        System.out.println("Solution found in " + attempts + " attempts");
    }

    public static void printBoard(int[] queens) {

        for (int row = 0; row < N; row++) {
            System.out.printf("%-1c", '|');
            for (int column = 0; column < N; column++) {
                System.out.printf("%-1c|", (queens[row] == column) ? 'Q' : ' ');
            }
            System.out.println();
        }       
    }

    public static boolean shareDiagonal(int x0, int y0, int x1, int y1) {

        int dy = Math.abs(y1 - y0);
        int dx = Math.abs(x1 - x0);

        return dx == dy;
    }

    public static boolean checkRowForCollision(int[] queens, int row) {

        for (int i = 0; i < row; i++) {

            if (shareDiagonal(i, queens[i], row, queens[row]))
                return true;    
        }
        return false;
    }

    public static boolean checkBoardForCollision(int[] queens) {

        for (int row = 0; row < queens.length; row++)
            if (checkRowForCollision(queens, row))
                return true;

        return false;
    }

    public static int[] shuffleBoard(int[] queens) {

        for (int i = queens.length - 1;  i > 0; i--) {

            int j = (int)(Math.random() * (i + 1));

            int temp = queens[i];
            queens[i] = queens[j];
            queens[j] = temp;
        }
        return queens;
    }
}
包装ch7;
公共课第七章第二十二章第八节{
公共静态void main(字符串[]args){
int queenCount=0;
int attemptCount=0;
布尔[]板=新布尔[8*8];
最终长时间限制=1;//毫秒
long startTime=System.currentTimeMillis();
而(皇后数<8){
int位置=placeQueen(板长);
if(检查位置(位置,板)和&!板[位置]){
板[位置]=真;
queenCount++;
}
长时间检查=System.currentTimeMillis();
if(时间检查-开始时间>时间限制){
透明板;
queenCount=0;
startTime=System.currentTimeMillis();
}         
System.out.println(“尝试”++++attemptCount);
System.out.println(queenscount+“queens放置”);
印刷板;
}   
}      
公共静态无效打印板(布尔[]板){
对于(int i=0;i=8时检查当前位置上方的每个字段
对于(int i=位置;i>=8;i-=8){
如果(董事会[i-8])
返回false;
}
返回true;
}
公共静态布尔checkBottom(int位置,布尔[]板){
//在i=9;i-=9)时检查当前位置下方的每个字段{
如果(董事会[i-9])
返回false;
}
返回true;
}
公共静态布尔checkTopRight(整型位置,布尔[]板){
//在i>=7时检查当前位置右上角的每个字段
对于(int i=位置;i>=7;i-=7){
如果(董事会[i-7])
返回false;
}
返回true;
}
公共静态布尔checkBottomRight(整型位置,布尔[]板){

//检查当前位置下方的每个字段,而我其中一个问题(可能还有更多问题)是在
checkTop
方法中

public static boolean checkTop(int position, boolean[] board)
{
    // Checks each field above the current position while i - 8 > - 1
    for (int i = position; i > (i - 8); i -= 8)
    {
        if ((i - 8) > -1)
        {
            if (board[i - 8])
                return false;
        }
    }
    return true;
}
在某些情况下,当该方法没有找到插槽(
board[i-8]=true
)并且
i
达到
7
的值时。在这一点之后,
for loop
i>(i-8)
)的条件将始终是
true
,而最外面的
if
的条件将始终是
在循环内(
if((i-8)>-1
)将始终为
false
。这将导致程序无限地停留在循环中

示例(
i
reats-5):

i=-5;
i>(i-8):-5>(-5-8=-13)(始终正确)

(i-8)>-1:-13>-1(false)对于i始终为false首先,大小为8的数组就足够了。
数组索引表示皇后所在的列,值表示行

表示第一列中的皇后位于第一行,第二个皇后位于第三行,第三个皇后位于第五行,以此类推

因此,当您放置新皇后时,请检查您添加它的行是否不在数组中。这样,您只需担心对角线碰撞

解决此问题的最简单方法是递归(回溯)。如果不允许,您可以使用堆栈模拟递归。如果也不允许,您可以使用8个嵌套循环-丑陋


您可以使用一个简单的技巧改进碰撞检查。其工作原理如下-
假设你的女王在第三排。
她对角攻击哪些细胞?
在…上
[0, 2, 4, 6, 1, 3, 5, 7] 
boolean canAdd(List<Integer> p, int newRow) {
    if (p.contains(newRow))
        return false;
    int insertIndex = p.size();
    for (int i = 0; i < p.size(); i++) {
        if (p.get(i) + (insertIndex - i) == newRow || p.get(i) - (insertIndex - i) == newRow)
            return false;
    }
    return true;
}
void solve(List<Integer> p, int index) {
    if (index == 8) {
        System.out.println(p);
        return;
    }

    for (int i = 0; i < 8; i++) {
        if (canAdd(p, i)) {
            p.add(i);
            solve(p, index + 1);
            p.remove(p.size() - 1);
        }
    }
}
solve(new ArrayList<Integer>(), 0);
package ch7;

public class Chapter_07_E22_EightQueens {

    static final int N = 8;

    public static void main(String[] args) {

        int[] queens = new int[N];
        int attempts = 0;

        for (int i = 0; i < N; i++) 
            queens[i] = i;

        while (checkBoardForCollision(queens)) {
            shuffleBoard(queens);
            attempts++;
        }
        printBoard(queens);
        System.out.println("Solution found in " + attempts + " attempts");
    }

    public static void printBoard(int[] queens) {

        for (int row = 0; row < N; row++) {
            System.out.printf("%-1c", '|');
            for (int column = 0; column < N; column++) {
                System.out.printf("%-1c|", (queens[row] == column) ? 'Q' : ' ');
            }
            System.out.println();
        }       
    }

    public static boolean shareDiagonal(int x0, int y0, int x1, int y1) {

        int dy = Math.abs(y1 - y0);
        int dx = Math.abs(x1 - x0);

        return dx == dy;
    }

    public static boolean checkRowForCollision(int[] queens, int row) {

        for (int i = 0; i < row; i++) {

            if (shareDiagonal(i, queens[i], row, queens[row]))
                return true;    
        }
        return false;
    }

    public static boolean checkBoardForCollision(int[] queens) {

        for (int row = 0; row < queens.length; row++)
            if (checkRowForCollision(queens, row))
                return true;

        return false;
    }

    public static int[] shuffleBoard(int[] queens) {

        for (int i = queens.length - 1;  i > 0; i--) {

            int j = (int)(Math.random() * (i + 1));

            int temp = queens[i];
            queens[i] = queens[j];
            queens[j] = temp;
        }
        return queens;
    }
}