数独生成器算法故障

时间:2018-03-24 16:40:31

标签: java sudoku variable-declaration

我在学校有一个项目,我必须创建一个数独计划。我设法让Solver算法工作但不是生成器。我花了很多时间在网上看看人们是否找到了工作方法,我找到了一个名叫Mark Fredrick Graves,Jr。(https://www.youtube.com/user/mfgravesjr)的人,他提供了一个关于数独创建的非常详细的代码他的GitHub上的网格(https://github.com/mfgravesjr/finished-projects/tree/master/SudokuGridGenerator)。但是,我觉得在找到访问线,列和方框的方程式方面,使用一维数组是不必要的。因此,我试图将他的代码翻译成二维数组,但我遇到了一些排序方法和一些变量表示的问题,如“int step =(a%2 == 0?rowOrigin + j:colOrigin + j * 9);”。我想知道的是如何将他使用的方法从一维数组转换为二维数组。以下是有问题的方法(代码片段)以及我自己翻译的一半尝试。

public int[] generateGrid(){
    ArrayList<Integer> arr = new ArrayList<Integer>(9);
    solvedGrid = new int[81];
    for(int i = 1; i <= 9; i++) arr.add(i);

    //loads all boxes with numbers 1 through 9
    for(int i = 0; i < 81; i++){
        if(i%9 == 0) {
            Collections.shuffle(arr);
        }
        int perBox = ((i / 3) % 3) * 9 + ((i % 27) / 9) * 3 + (i / 27) * 27 + (i % 3);
        solvedGrid[perBox] = arr.get(i%9);
    }

    //tracks rows and columns that have been sorted
    boolean[] sorted = new boolean[81];

    for(int i = 0; i < 9; i++){
        boolean backtrack = false;
        //0 is row, 1 is column
        for(int a = 0; a<2; a++){
            //every number 1-9 that is encountered is registered
            boolean[] registered = new boolean[10]; //index 0 will intentionally be left empty since there are only number 1-9.
            int rowOrigin = i * 9;
            int colOrigin = i;

            ROW_COL: for(int j = 0; j < 9; j++){
                //row/column stepping - making sure numbers are only registered once and marking which cells have been sorted
                int step = (a%2==0? rowOrigin + j: colOrigin + j*9);
                int num = solvedGrid[step];

                if(!registered[num]) {
                    registered[num] = true;
                }else {
                    //if duplicate in row/column
                    //box and adjacent-cell swap (BAS method)
                    //checks for either unregistered and unsorted candidates in same box,
                    //or unregistered and sorted candidates in the adjacent cells
                    for(int y = j; y >= 0; y--){
                        int scan = (a%2==0? i * 9 + y: i + 9 * y);
                        if(solvedGrid[scan] == num){
                            //box stepping
                            for(int z = (a%2==0? (i%3 + 1) * 3: 0); z < 9; z++){
                                if(a%2 == 1 && z%3 <= i%3) {
                                    continue;
                                }
                                int boxOrigin = ((scan % 9) / 3) * 3 + (scan / 27) * 27;
                                int boxStep = boxOrigin + (z / 3) * 9 + (z % 3);
                                int boxNum = solvedGrid[boxStep];
                                if((!sorted[scan] && !sorted[boxStep] && !registered[boxNum]) || (sorted[scan] && !registered[boxNum] && (a%2==0? boxStep%9==scan%9: boxStep/9==scan/9))){
                                    solvedGrid[scan] = boxNum;
                                    solvedGrid[boxStep] = num;
                                    registered[boxNum] = true;
                                    continue ROW_COL;
                                }else if(z == 8) { 
                                    //if z == 8, then break statement not reached: no candidates available
                                    //Preferred adjacent swap (PAS)
                                    //Swaps x for y (preference on unregistered numbers), finds occurence of y
                                    //and swaps with z, etc. until an unregistered number has been found
                                    int searchingNo = num;

                                    //noting the location for the blindSwaps to prevent infinite loops.
                                    boolean[] blindSwapIndex = new boolean[81];

                                    //loop of size 18 to prevent infinite loops as well. Max of 18 swaps are possible.
                                    //at the end of this loop, if continue or break statements are not reached, then
                                    //fail-safe is executed called Advance and Backtrack Sort (ABS) which allows the 
                                    //algorithm to continue sorting the next row and column before coming back.
                                    //Somehow, this fail-safe ensures success.
                                    for(int q = 0; q < 18; q++){
                                        SWAP: for(int b = 0; b <= j; b++){
                                            int pacing = (a%2==0? rowOrigin+b: colOrigin+b*9);
                                            if(solvedGrid[pacing] == searchingNo){
                                                int adjacentCell = -1;
                                                int adjacentNo = -1;
                                                int decrement = (a%2==0? 9: 1);

                                                for(int c = 1; c < 3 - (i % 3); c++){
                                                    adjacentCell = pacing + (a%2==0? (c + 1)*9: c + 1);

                                                    //this creates the preference for swapping with unregistered numbers
                                                    if((a%2==0 && adjacentCell >= 81) 
                                                            || (a%2==1 && adjacentCell % 9 == 0)) {
                                                        adjacentCell -= decrement;
                                                    }else {
                                                        adjacentNo = solvedGrid[adjacentCell];
                                                        if(i%3!=0
                                                                || c!=1 
                                                                || blindSwapIndex[adjacentCell]
                                                                || registered[adjacentNo]) {
                                                            adjacentCell -= decrement;
                                                        }
                                                    }
                                                    adjacentNo = solvedGrid[adjacentCell];

                                                    //as long as it hasn't been swapped before, swap it
                                                    if(!blindSwapIndex[adjacentCell]){
                                                        blindSwapIndex[adjacentCell] = true;
                                                        solvedGrid[pacing] = adjacentNo;
                                                        solvedGrid[adjacentCell] = searchingNo;
                                                        searchingNo = adjacentNo;

                                                        if(!registered[adjacentNo]){
                                                            registered[adjacentNo] = true;
                                                            continue ROW_COL;
                                                        }
                                                        break SWAP;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    //begin Advance and Backtrack Sort (ABS)
                                    backtrack = true;
                                    break ROW_COL;
                                }
                            }
                        }
                    }
                }
            }

            if(a%2==0) {
                for(int j = 0; j < 9; j++) {
                    sorted[i*9+j] = true; //setting row as sorted
                }
            }else if(!backtrack) {
                for(int j = 0; j < 9; j++) {
                    sorted[i+j*9] = true; //setting column as sorted
                }
            }else {//reseting sorted cells through to the last iteration
                //backtrack = false;

                for(int j = 0; j < 9; j++) {
                    sorted[i*9+j] = false;
                }
                for(int j = 0; j < 9; j++) { 
                    sorted[(i-1)*9+j] = false;
                }
                for(int j = 0; j < 9; j++) {
                    sorted[i-1+j*9] = false;
                }

                for(int j = 0; j < 81; j++) {
                    sorted[j] = false;
                }
                i-=2;
            }
        }
    }

    if(!isPerfect(solvedGrid)) {
        throw new RuntimeException("ERROR: Imperfect grid generated.");
    }

    return solvedGrid;
}

我的代码(未完成)

public int[][] generateGrid(){
    ArrayList<Integer> arr = new ArrayList<Integer>(9);
    ArrayList<Integer> values = new ArrayList<Integer>(9);
    solvedGrid = new int[9][9];
    for(int i = 1 ; i <= 9; i++) {
        arr.add(i);
        values.add(i);
    }

    //Fill all boxes with number 1 to 9
    for(int i = 0; i < 9; i++) {
        for(int j = 0; j < 9; j++) {
            if(j == 0) {
                Collections.shuffle(arr);
            }
            solvedGrid[(i/3)*3+(j/3)][(i%3)*3+(j%3)] = arr.get(j);
        }
    }

    //boolean[][] sorted = new boolean[9][9];

    for(int i = 0; i < 9; i++) {
        for(int j = 0; j < 9; j++) {
            int[] rowColValues = new int[9];
            rowColValues[j] = solvedGrid[0][j];
            ArrayList<Integer> occurence = new ArrayList<Integer>();
            for(int k = 0; k < rowColValues.length; k++) {
                occurence.add((k+1), occurence.get(k+1)+1);
                if(occurence.get(k+1) != 1) {
                    //swap with number in the box that isn't already in rowColValues
                    //Not sure how to do this...
                    //Create a method that takes the correct variables as parameters ?
                    break;
                }
            }
            //Read the sudoku row then column wise and swap values that already exist in the column or row.
        }
    }

    print2DGrid(solvedGrid);

    return solvedGrid;
}

0 个答案:

没有答案