退出void递归Java函数的更顺畅的方法

时间:2015-12-29 18:23:42

标签: java recursion

所以我写了这个函数,其行为类似于Knuth的算法X.仅仅是为了说明 - 该函数需要一个可能行的大矩阵,其中它试图选择构成合法解决方案的组合。 。

问题是,一旦我们找到了解决方案,由于它的空白,该函数不会返回任何内容而只是回溯(这意味着它会在递归深度中的每个级别打印出数独的数据)。

有关如何在找到解决方案时结束功能的任何建议?我目前正在使用System.exit(0),但这不是很好,因为程序会在你找到解决方案的那一刻结束(所以你想要做的任何事情都是不可能的 - 例如在sudokus数组上运行函数和解决每一个问题。)

代码在这里:

public static void solve(ArrayList<int[]> solution, ArrayList<int[]> coverMatrix) {

    if (Arrays.equals(solvedCase, workCase)) {
        //this means we found the solution

        drawSudoku(testOutput);
        System.exit(0);

    } else {

        //find the column we didnt yet cover
        int nextColToCover = findSMARTUnsatisfiedConstraint(coverMatrix, workCase);

        //get all the rows that MIGHT solve this problem
        ArrayList<int[]> rows = matchingRows(coverMatrix, nextColToCover);

        //recusively try going down every one of them
        for (int i = 0; i < rows.size(); i++) {

            //we try this row as solution
            solution.add(rows.get(i));

            //we remove other rows that cover same columns (and create backups as well)
            removeOtherRowsAndAdjustSolutionSet(coverMatrix);

            if (isSolutionPossible(coverMatrix)) {
                solve(solution, coverMatrix);
            }

            // here the backtracking occurs if algorithm can't proceed
            // if we the solution exists, do not rebuild the data structure
            if (!Arrays.equals(solvedCase, workCase)) {
                restoreTheCoverMatrix(coverMatrix);
            }
        }
    }
}

3 个答案:

答案 0 :(得分:0)

如果我理解正确,您希望在获得第一个解决方案时结束递归。您可以通过为方法设置布尔返回类型来实现此目的,并在获得第一个解决方案时返回true:。

    public static boolean solve(ArrayList<int[]> solution, ArrayList<int[]> coverMatrix) {

if (Arrays.equals(solvedCase, workCase)) {
    //this means we found the solution

    drawSudoku(testOutput);
    return true;

} else {

    //find the column we didnt yet cover
    int nextColToCover = findSMARTUnsatisfiedConstraint(coverMatrix, workCase);

    //get all the rows that MIGHT solve this problem
    ArrayList<int[]> rows = matchingRows(coverMatrix, nextColToCover);

    //recusively try going down every one of them
    for (int i = 0; i < rows.size(); i++) {

        //we try this row as solution
        solution.add(rows.get(i));

        //we remove other rows that cover same columns (and create backups as well)
        removeOtherRowsAndAdjustSolutionSet(coverMatrix);

        if (isSolutionPossible(coverMatrix)) {
            boolean result = solve(solution, coverMatrix);
            if(result  == true) return result;//else continue
        }

        // here the backtracking occurs if algorithm can't proceed
        // if we the solution exists, do not rebuild the data structure
        if (!Arrays.equals(solvedCase, workCase)) {
            restoreTheCoverMatrix(coverMatrix);
        }
    }
    return false;
}

}

答案 1 :(得分:0)

您可以将AtomicReference类与Boolean

一起使用
public static void solve(ArrayList<int[]> solution, ArrayList<int[]> coverMatrix, AtomicReference<Boolean> test) {
if (Arrays.equals(solvedCase, workCase)) {
    //this means we found the solution
    drawSudoku(testOutput);
    test.set(true);//System.exit(0);
}
solve(solution, coverMatrix, test);
if(!test.get())
{
    // here the backtracking occurs if algorithm can't proceed
    // if we the solution exists, do not rebuild the data structure
    if (!Arrays.equals(solvedCase, workCase)) {
        restoreTheCoverMatrix(coverMatrix);
    }
}

您可以像这样调用您的方法(只需将Boolean初始化为false):

public static void main(String[] args)
{
    AtomicReference<Boolean> test1 = new AtomicReference<Boolean>();
    test1.set(false);
    solve(***, ***, test1);
}

答案 2 :(得分:0)

你可能会滥用异常的概念,虽然我不推荐它。

首先定义一个自定义异常类。

public class SuccessException extends Exception {}

在成功时抛出一个实例。

if (Arrays.equals(solvedCase, workCase)) {
    drawSudoku(testOutput);
    throw new SuccessException();
}

最初在try块中调用该函数。

try {
   solve(solution, coverMatrix);
} catch(SuccessException e) {
   /* Solution found! */
}