回溯到sudoku求解每次选择随机单元和随机值的逻辑

Backtracking logic for sudoku solving choosing random cell and random value each time

本文关键字:随机 单元 选择 sudoku 回溯      更新时间:2023-10-16

我正在尝试为sudoku(9x9 grid)实现回溯求解器,非常基础。

伪代码逻辑:

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(包括)。请记住,C 使用0个索引内存,因此您只能访问索引0-8包含索引。

编辑:只是为了张贴后期的修复。

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