-1

数独パズルを生成するプログラムに取り組んでいます。これを行うためにバックトラッキング アルゴリズムを使用しようとしましたが、プログラムが機能しません。プログラムは無限に実行され、解を返すことはありません。それが単なる小さな問題なのか、それともバックトラッキング アルゴリズムの書き方を誤解しているのかはわかりません。

package sudoku;

import java.util.Random;

public class Puzzle {

    // 9x9 puzzle
    private int puzzle[][] = new int[9][9];

    // generate a completely solved sudoku board
    public int[][] generate() {

        Random gen = new Random();

        // add each number to the board square by square
        for (int y = 0; y < 9; y++) {
            for (int x = 0; x < 9; x++) {

                // generate random number 1-9
                int num = gen.nextInt(9) + 1;

                int count = 0;
                boolean valid = false;

                while (valid == false) {

                    // check if number is valid
                    if (checkRow(num, x) && checkCol(num, y)
                            && checkSection(num, x, y)) {

                        // add number to the board
                        puzzle[x][y] = num;

                        // exit loop, move on to next square
                        valid = true;

                    } else {

                        // try next number
                        if (num == 9) {
                            num = 1;
                        } else {
                            num++;
                        }

                        // increase counter.
                        count++;

                        // if counter reached 9, then all numbers were tried and
                        // none were valid, begin backtracking
                        if (count == 9) {

                            // go back 1 square
                            if (x == 0) {
                                x = 8;
                                y--;
                            } else {
                                x--;
                            }

                            // empty square
                            puzzle[x][y] = 0;

                            //reset count
                            count = 0;

                        }

                    }

                }
            }
        }

        return puzzle;
    }

    // check each element of the row for num, if num is found return false
    private boolean checkRow(int num, int row) {

        for (int i = 0; i < 9; i++) {
            if (puzzle[row][i] == num) {
                return false;
            }
        }

        return true;
    }

    // check each element of the column for num, if num is found return false
    private boolean checkCol(int num, int col) {

        for (int i = 0; i < 9; i++) {
            if (puzzle[i][col] == num) {
                return false;
            }
        }

        return true;
    }

    // check each element of the section for num, if num is found return false
    private boolean checkSection(int num, int xPos, int yPos) {

        int[][] section = new int[3][3];
        section = getSection(xPos, yPos);

        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (section[i][j] == num)
                    return false;
            }
        }
        return true;

    }

    // return the 3x3 section the given coordinates are in
    private int[][] getSection(int xPos, int yPos) {

        int[][] section = new int[3][3];
        int xIndex = 3 * (xPos / 3);
        int yIndex = 3 * (yPos / 3);

        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                section[i][j] = puzzle[xIndex + i][yIndex + j];
            }
        }

        return section;

    }
}
4

2 に答える 2

1

いくつかの問題が発生する可能性があります。例を挙げます。

バックトラッキングが機能しない主な理由は、バックトラッキングを行っていないためです。ツリー内の 1 つの状態だけに戻ります。バックトラックとは、サブツリーのすべての可能性をチェックし、(どれも有効でない場合) サブツリーの高さに関係なく、そのサブツリーを無視することを意味します。

どれどれ。あなたのアプローチは、「すべての数字を一列に並べて、正方形が完成することを願っています。現在の正方形の処理でエラーが発生した場合は、前の正方形をクリアしてください」です。

最初は問題ありません。最初の行を取得してもエラーは発生しません。しかし、次のようにして最初の 8 行を完了した可能性を考えてみてください。

1
2
3
----
4
5
6
---
79
832|179|456     
x

の有効な値がありませんx。あなたのアルゴリズムは何をしますか?戻って 6 を変更してみてください。当然のことながら、これは 6 を 6 に置き換えて、値を に設定し直すことで終了しますx

私がインターネットで見つけた Sudokus ジェネレーターには後戻りがありません。有効なソリューションを取得し、それに一連の変更を加えて、すべての変更が有効なソリューションをもたらすようにします (詳細については、Google に問い合わせてください)。

バックトラッキングを使用したい場合は、各ステップで、数独がまだ解けるかどうか (または、少なくとも「壊れていない」かどうか) をスキャンする必要があります。そして、解決不可能な組み合わせを繰り返さない方法があります。

さらに、数字を並べようとすると(それは意見です)、最初にあまりにも強い制約を追加するようです。最初の 2 行を埋めるのは簡単ですが、ソリューション全体を調整します (最初の行を埋めても影響はないことに注意してください! :-D)。

于 2013-06-22T23:26:23.627 に答える
0

これが問題に取り組む良い方法だとは思いません。残念ながら、私はあなたのための解決策を持っていませんが、一度count == 9、あなたが変わることがわかりますx and y.これは必ずしも良いことではありません. while(!valid)それにもかかわらず、ループを終了する方法を提供していません。実際にバックトラックするには、に変更validする必要があります。trueただし、これではメソッドが機能しません。

于 2013-06-22T23:57:42.893 に答える