递归错误

Error from Recursion

对于一个项目,我必须编写一个程序来递归地解决所有 92 个解决方案中的 8 Queens Puzzle。在递归地使 "main" 方法 运行 之前,该程序工作正常。奇怪的是它在与 "main" 方法的循环(包括在 toString 方法中)无关的点抛出错误。我试图在任何可能的地方放置递归调用,甚至我的导师也无法弄清楚。我还必须提到,将循环的递归调用移动到它通过错误的位置,并且程序与引发错误的解决方案不一致。

import java.util.Scanner;
    public class NonAttackingQueens {
        private Scanner scan = new Scanner(System.in);
        //Row
        private int r = 0;
        //Column
        private int c = 0;
        private int solution = 1;
        private int[] taken = {9,9,9,9,9,9,9,9};
        private int[][] board = {
        {0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0}};

        public static void main(String[] args){
            NonAttackingQueens board = new NonAttackingQueens();
        }

        public NonAttackingQueens(){
            place();
        }

        //This is the main method that runs everything.
        private void place(){
            //There are only 92 solutions, and this stops it after the 92th iteration
            while (solution <= 92){
                //If r==8 then it has found a solution
                if (r == 8){
                    System.out.println(this);
                    r = 7;
                    //This forces the program to continue
                    //It removes the last queen tries to move it right one
                    backTrack(0);

                    //The Scanner is used to pause the program after every solution
                    //Just hit enter to continue
                    scan.nextLine();

                    //place();
                }
                else {
                    //If it is not a legal spot
                    if (poss()){
                        board[r][c] = 1;

                        //The taken array is the location of all the queens
                        //It works the same as a regular coordinate system
                        //but being an array is a little more difficult to read
                        /*
                         *   0 1 2 3 4 5 6 7
                         * 0 9 9 9 9 9 3 9 9
                         * 1 9 9 9 9 9 3 9 9
                         * 2 9 9 9 9 9 3 9 9
                         * 3 9 9 9 9 9 3 9 9
                         * 4 9 9 9 9 9 3 9 9
                         * 5 9 9 9 9 9 3 9 9
                         * 6 9 9 9 9 9 3 9 9         
                         * 7 9 9 9 9 9 3 9 9
                         * 
                         * {9,9,9,9,9,3,9,9}
                         * 
                         */
                        //The element of the array is equal to its column
                        //The value of the element is equal to its row
                        //So a queen in row 3 column 5 is equal
                        //is equal to taken[5]=3;
                        //Or the entire first solution would have to array equal
                        //{0,6,4,7,1,3,2,5}
                        taken[c] = r;

                        r++;
                        c = 0;

                        //place();
                    }
                    //Then find a new one
                    else {
                        findNext();
                        //This is how it would run recursively........
                        //If it did not give a stack overflow
                        //this.place();
                    }
                }
                place();
            }
        }

        //Tests if it is legal to move here
        private boolean poss(){
            if (c >= 8 || taken[c] != 9 || diag()) return false;

            else return true;
        }

        //Checks for any diagonal attacks
        //It's logic is opposite of the other two conditions in the .poss()
        private boolean diag(){
            int left = c;
            int right = c;
            int tmpR = r;

            boolean found = false;

            while (left >= 0 && tmpR >= 0){
                if (board[tmpR][left] == 1) {
                    found = true;
                }
                tmpR -= 1;
                left -= 1;
            }

            tmpR = r;

            //These worked intuitively
            //They go up one row then left or right one column
            //If it hits a 1 then there's a diagonal
            //If it hits -1 then there is not
            while (right <= 7 && tmpR >= 0 && found != true){
                if (board[tmpR][right] == 1){
                    found = true;
                }
                tmpR -= 1;
                right += 1;
            }
            return found;
        }

        //This literally keeps going right until it finds an opening or hits the right side
        //Then it does the back track method
        private void findNext(){
            //The last column did not work so it immediately goes to the next one
            c++;
            //100% recursive
            if (c < 8){
                //Tests if it is a legal spot
                if (poss()){
                    return;
                }
                //If not then go to the next column
                else findNext();
            }
            //If it hits the right side then it back tracks
            else {
                //Nothing on this row so immediately go to the one before
                r--;
                backTrack(0);
            }
        }

        private void backTrack(int x){
            if (x < taken.length){
                //This is the main reason why I have the taken array
                //It checks every array element until it finds the one equal to the
                //element that needs to be removed.
                //It changes that element to 9 and removes it from the board
                //It then makes c equal one more than the column it just removed the element from
                if (taken[x] == r){
                    taken[x] = 9;
                    board[r][x] = 0;
                    c = x + 1;
                    return;
                }
                else {
                    x++;
                    backTrack(x);
                }
            }

        }

        public String toString(){
            String result="Solution: "+solution+"\n";
            for (int i=0; i<board.length; i++){
                for (int j=0; j<board[i].length; j++){
                    result += board[i][j];
                }
                result += "\n";
            }
            solution++;
            return result;
        }
    }   

要使其 运行 递归,请将 place 方法中的 while 更改为 if 并取消注释 .place() 方法。

如果您在递归调用之外遇到溢出,则表明计数器导致某些内容超出范围。要么,要么递归 运行 太深,这样你就 运行 出栈了 space。查看除此之外使用的数组;我建议打印出相关计数器的值以查看发生的情况。

如果我遇到溢出错误,计数器通常是我开始的地方;特别是当我处理数组时。

希望对您有所帮助!