我正在尝试为数独(9x9网格)实现回溯求解器,非常基本。

伪代码逻辑:

backtrack():
choose random **empty** cell

generate random value (1 ....9)

check if it fits(or is good for - row,column,region):
               if yes - occupy this cell , recurse

               if no -  put the cell value to zero


约束:在相同的行,相同的列和相同的区域中没有相似的数字。(区域-3x3块)

我看不到我的逻辑缺陷,但它存在!

这是c ++代码:

bool basic_sudoku_with_random_picking( int table[][9] ){

    if(find_empty_cell(table) == false ) return true ;// no empty cells? success!
    int row = -1 ;
    int column = -1 ;
    int x, y ;
    x = 1 + rand() % 9 ;//generate random x
    y = 1 + rand() % 9 ;//gen random y

    if( table[x][y] == 0){// see if the cell is zero (zero - free)
        row = x ;
        column = y ;
        int try_num = 1 + rand()% 9 ;// found empty cell - try  random number on it!
        if( is_good(table, row,column, try_num) ){
            table[row][column] = try_num ;
            return ( basic_sudoku_with_random_picking(table) ) ;
        }
        else{ table[row][column] = 0 ;
            return false ;

        }
    }
    else return basic_sudoku_with_random_picking(table) ;

}


//check row
bool is_row_good(int table[][9], int row , int num){
    for(int column = 0  ; column < 9 ; column++ ){
        if (table[row][column] == num ){
            return false ;}
    }

    return true ;
}
//check column
bool is_column_good(int table[][9], int column , int num){
    for(int row = 0  ; row < 9 ; row++ ){
        if (table[row][column] == num ){
            return false ;}

    }
    return true ;
}
//check block- region
bool check_region(int table[][9], int x1, int y1, int x2, int y2, int check){
    for(int i = x1; i <= x2 ;i++){
        for(int j = y1 ; j <=y2 ;j++){
            if(table[i][j] == check){

                return false ;}

        }
        cout <<endl ;
    }
    return true ;
}
bool is_block_good(int table[][9], int i, int j , int num){

    if(i >= 0 && i <=2){
        if( j <= 2 )      check_region(table,0,0,2,2, num) ;// 1 region
        if(j >= 3 && j<=5)check_region(table,0,3,2,5, num) ;//2 region
        if(j >=6  && j<=8)check_region(table,0,6,2,8, num) ;//3 region
    }

    if(i >=3 && i <=5){
        if(j <=2 )        check_region(table,3,0,5,2, num) ;//4 block
        if(j >= 3 && j<=5)check_region(table,3,3,5,5, num) ;//5 block
        if(j >= 6 && j<=8)check_region(table,3,6,5,8, num) ;//6 block

    }

    if( i >=6 && i <=8){
        if(j<= 2)         check_region(table,6,0,8,2, num) ;//7 block
        if(j >= 3 && j<=5)check_region(table,6,3,8,5, num) ;// 8 block
        if(j >= 6 && j<=8)check_region(table,6,6,8,8, num) ;//9 block
    }
}

//check all 3 constraints
bool is_good(int table[][9], int i, int j, int try_num){
    //cout << "CHECKING CELL in general" <<endl ;
    return (is_row_good   (table, i, try_num) &&
            is_column_good(table, j, try_num) &&
            is_block_good (table, i , j,try_num) ) ;
}

bool find_empty_cell(int table[][9]){
    for(int i = 0 ; i  < 9 ; i++){
        for(int j = 0 ; j < 9 ; j++){
            if( table[i][j] == EMPTY_CELL){// found empty cell
                return true ;
            }
        }
    }
    return false ;
}

最佳答案

您遇到的实际问题是什么?

这是我发现的一个问题:

x = 1 + rand() % 9 ;//generate random x
y = 1 + rand() % 9 ;//gen random y
   if( table[x][y] == 0){
      ...


因为table是作为table[/*something*/][9]存储的2d数组,所以您可能会尝试访问超出数组范围的内存,因为y可以取值1-9(包括1和9)。请记住,C ++使用0索引的内存,因此您只应访问0-8(含0)的索引。

编辑:
只是为了发布后代修复程序。

x = rand() % 9 ;//generate random x
y = rand() % 9 ;//gen random y

关于c++ - 数独解决每次回溯选择随机单元格和随机值的回溯逻辑,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21412129/

10-13 09:31