数独生成:它进入循环

时间:2014-04-21 13:44:13

标签: c++ algorithm sudoku

我正在尝试使用数独生成器算法,这是我的c ++代码:

void generateSudoku(num sudoku[][N])
{   int i,j,k;
    int vett[N],n,old;
    //clean the sudoku matrix filling it with -1
    for(i=0;i<N;i++)
        for(j=0;j<N;j++)
            sudoku[i][j].val=-1;
    //generate the sudoku
    for(i=0;i<N;){
        for(j=0;j<N;){
            k=0;
            clean(vett,N);  //fills the vector with -1
            old=sudoku[i][j].val; //saves the actual value
            do{
                if(k<9){
                    do{
                        n=rand()%9+1;
                    }while(find(vett,N,n)); //generate n while it already exists in vett
                    vett[k++]=n;
                    if((!(exists(sudoku,i,j,n))) && (n!=old)){ //if it not exists on row, column and sub-matrix and it's different between the old value, it's OK
                        sudoku[i][j++].val=n;
                        if(j==N) i++;
                        k=10;
                        }
                }
                else{
                    sudoku[i][j].val=-1;  
                    if(j>0) j--;
                    else if(i>0){
                        j=N-1;
                        i--;
                    }
                    k=10;
                }

            }while(k<=9);
        }
    }
}

它进入循环,我知道原因:

2 7 6 | 9 1 3 | 4 5 8
4 3 9 | 5 7 2 | * *

在这个例子中,它继续生成6-1然后1-6,其中有*,它永远不会完成。但即使我理解为什么它循环,我也不知道纠正它的最佳方法。有人能帮助我吗?

2 个答案:

答案 0 :(得分:1)

你必须进一步回溯。第二行的最后一个单元格中没有有效条目。我不确定贪婪算法是否会作为数独生成器工作。我会尝试使用基于堆栈树的方法。

答案 1 :(得分:0)

以下可能有所帮助(未经测试):

void restore(std::vector<int>& v) {
    v.clear();
    for (int i = 0; i != 9; ++i) {
        v.push_back(1 + i);
    }
}

void generate(int (&sudoku)[9][9])
{
    std::vector<int> allowedSymbols[9][9];

    bool succeed = true;
    for(int i = 0, j = 0; i != 9; ) {
        if (succeed) {
            restore(allowedSymbols[i][j]);
            succeed = false;
        }
        while (!allowedSymbols[i][j].empty()) {
            int index = rand() % allowedSymbols[i][j].size();

            if (!exists(sudoku, i, j, allowedSymbols[i][j][index])) { //if it not exists on row, column and sub-matrix, it is OK
                succeed = true;
                break;
            }
            allowedSymbols[i][j].erase(allowedSymbols[i][j].begin() + index);
        }
        if (succeed) {
            ++j;
            if (j == 9) {
                j = 0;
                ++i;
            }
        } else {
            // backtrack.
            --j;
            if (j == -1) {
                j = 8;
                --i;
            }
            allowedSymbols[i][j].erase(std::find(allowedSymbols[i][j].begin(),
                                                 allowedSymbols[i][j].end(),
                                                 sudoku[i][j]));
        }
    }
}