迭代蛮力数独求解器

时间:2015-04-29 09:16:38

标签: java nested sudoku

我正在尝试实现一个迭代的Sudoku解算器。为了避免递归,我使用了堆栈,但是我的管理有问题。起始板由一个String数组(变量'输入'在下面的代码中)表示,其中每个元素由3个数字组成:[row,col]及其值(即" 006"表示第1行和第1列中的元素是6)并由构造函数转换为int数组。当我运行它时,我无法得到解决方案,因此嵌套for循环中可能存在错误。任何帮助表示赞赏。

import java.util.ArrayList;

public class SudokuSolver {

    private int[][] matrix = new int[9][9];
    private String[] input = { "006", "073", "102", "131", "149", "217",
        "235", "303", "345", "361", "378", "422", "465", "514", "521",
        "548", "582", "658", "679", "743", "752", "784", "818", "883" };

    private ArrayList<int[][]> stack = new ArrayList<>();

    public SudokuSolver() {
        // Building the board based on input array
        for (int n = 0; n < input.length; ++n) {
            int i = Integer.parseInt(input[n].substring(0, 1));
            int j = Integer.parseInt(input[n].substring(1, 2));
            int val = Integer.parseInt(input[n].substring(2, 3));
            matrix[i][j] = val;
        }
        stack.add(matrix);
    }

    private boolean isSolution(int[][] cells) {
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                if(cells[i][j] == 0)
                    return false;
            }
        }
        return true;
    }

    private boolean isValid(int i, int j, int val, int[][] cells) {
        for (int k = 0; k < 9; k++)
            if (val == cells[k][j])
                return false;
        for (int k = 0; k < 9; k++)
            if (val == cells[i][k])
                return false;
        return true;
    }

    private boolean iterativeSudokuSolver() {
        int[][] current = null;

        while(stack.size() > 0 && !isSolution(stack.get(0))) {
            current = stack.remove(0);

            for (int row = 0; row < 9; row++) {
                for (int col = 0; col < 9; col++) {
                    if (current[row][col] == 0) {
                        for (int val = 1; val <= 9; val++) {
                            if (isValid(row, col, val, current)) {
                                current[row][col] = val;
                                stack.add(0, current);
                                break;
                            }
                        }
                    }
                }
            }
        }
        if (current != null && isSolution(current))
            return true;
        else
            return false;
    }

    public static void main(String [] args) {
        SudokuSolver sudokuSolver = new SudokuSolver();
        boolean result = sudokuSolver.iterativeSudokuSolver();

        if (result)
            System.out.println("Sudoku solved");
        else
            System.out.println("Sudoku not solved");
    }
}

1 个答案:

答案 0 :(得分:0)

  1. 通过添加和删除ArrayList的第0个元素的堆栈实现是一个非常糟糕的主意:它强制每次都将数组的整个内容向前移回。使用LinkedList或修改列表的末尾。
  2. 当您在堆栈中来回添加和删除相同的矩阵实例时,它仍然是相同的矩阵对象,即使您可以将其称为“当前”或任何其他名称。这意味着当您更改矩阵中的某些内容然后将其从堆栈中删除时,更改将保留在那里(并且在堆栈的每个其他元素中,它们都是指向同一对象的相同链接)。您的解决方案的逻辑看起来需要将解决方案的先前状态存储在堆栈中,如果是这样 - 每次都分配一个新数组并复制数据(也不是很有效,但尝试从那里开始)。
  3. 一个好问题必须具体。 “为什么这不起作用?”这是一个糟糕的问题。首先解决明显的问题,调试,如果困惑提供有关程序状态的更多信息(数据输入,例如步骤#1 ... N的数据)