csolversudoku

testing sudoku puzzles using backtrack algorithm in c


backtrack solver algorithm for sudoku puzzles in c which counts possible solutions

I found this c code implementing a sudoku solver backtrack algorithm and it is able to find a solution to any sudoku puzzle that has at least one solution. i would like to know if there is an easy adjustment, that it is able to tell if there is more than one solution at a given sudoku puzzle

#include <stdio.h>

int matrix[9][9]={0};    //row*col sudoku numbers

int test[9][9] = {
     {5, 3, 0, 0, 7, 0, 0, 0, 0} ,
     {6, 0, 0, 1, 9, 5, 0, 0, 0} ,
     {0, 9, 8, 0, 0, 0, 0, 6, 0} ,
     {8, 0, 0, 0, 6, 0, 0, 0, 3} ,
     {4, 0, 0, 8, 0, 3, 0, 0, 1} ,
     {7, 0, 0, 0, 2, 0, 0, 0, 6} ,
     {0, 6, 0, 0, 0, 0, 2, 8, 0} ,
     {0, 0, 0, 4, 1, 9, 0, 0, 5} ,
     {0, 0, 0, 0, 8, 0, 0, 7, 9}
};

int veryhard[9][9] = {
     {8, 0, 0,  0, 0, 0,  0, 0, 0} ,
     {0, 0, 3,  6, 0, 0,  0, 0, 0} ,
     {0, 7, 0,  0, 9, 0,  2, 0, 0} ,

     {0, 5, 0,  0, 0, 7,  0, 0, 0} ,
     {0, 0, 0,  0, 4, 5,  7, 0, 0} ,
     {0, 0, 0,  1, 0, 0,  0, 3, 0} ,

     {0, 0, 1,  0, 0, 0,  0, 6, 8} ,
     {0, 0, 8,  5, 0, 0,  0, 1, 0} ,
     {0, 9, 0,  0, 0, 0,  4, 0, 0}
};

int fivesolution[9][9] = {
     {0, 0, 0,  0, 0, 0,  0, 0, 0} ,
     {0, 1, 6,  0, 3, 0,  0, 5, 0} ,
     {0, 9, 0,  0, 0, 2,  0, 0, 8} ,

     {0, 0, 7,  0, 0, 8,  0, 0, 0} ,
     {0, 6, 0,  0, 1, 0,  3, 4, 5} ,
     {2, 5, 1,  0, 4, 0,  0, 0, 0} ,

     {0, 0, 0,  0, 9, 0,  0, 8, 0} ,
     {0, 4, 0,  5, 2, 1,  6, 7, 0} ,
     {0, 2, 0,  0, 8, 3,  0, 0, 0}
};

int moresolution[9][9] = {
     {1, 0, 0,  0, 0, 0,  0, 0, 0} ,
     {0, 0, 0,  0, 0, 0,  0, 0, 0} ,
     {0, 0, 0,  0, 0, 0,  0, 0, 0} ,

     {0, 0, 0,  0, 0, 0,  0, 0, 0} ,
     {0, 0, 0,  0, 0, 0,  0, 0, 0} ,
     {0, 0, 0,  1, 0, 0,  0, 0, 0} ,

     {0, 0, 0,  0, 0, 0,  0, 0, 0} ,
     {0, 0, 0,  0, 0, 0,  0, 0, 0} ,
     {0, 0, 0,  0, 0, 0,  0, 0, 0}
};

int nosolution[9][9] = {
     {0, 0, 0,  0, 0, 0,  0, 0, 0} ,
     {0, 1, 6,  0, 3, 0,  0, 5, 0} ,
     {0, 9, 0,  0, 0, 2,  0, 0, 8} ,

     {0, 0, 7,  0, 0, 8,  0, 0, 0} ,
     {0, 6, 0,  0, 1, 0,  3, 4, 5} ,
     {0, 0, 0,  0, 0, 0,  0, 0, 0} ,

     {0, 0, 0,  0, 0, 0,  0, 8, 0} ,
     {0, 4, 0,  0, 2, 1,  6, 7, 0} ,
     {0, 5, 0,  0, 4, 3,  0, 0, 0}
};

int usedInRow(int matrix[9][9],int row,int num) {
    for (int col = 0; col < 9; col++) {
        if (matrix[row][col] == num) {
            return 1;
        }
    }
    return 0;
}

int usedInCol(int matrix[9][9],int col,int num) {
    for (int row = 0; row < 9; row++) {
        if (matrix[row][col] == num) {
            return 1;
        }
    }
    return 0;
}

int usedInBox(int matrix[9][9],int boxStartRow,int boxStartCol,int num) {
    for (int row = 0; row < 3; row++) {
        for (int col = 0; col < 3; col++) {
            if (matrix[row + boxStartRow][col + boxStartCol] == num) {
                return 1;
            }
        }
    }
    return 0;
}


 int isSafe(int matrix[9][9],int row,int col,int num) {
    return (
        !usedInRow(matrix, row, num) &&
        !usedInCol(matrix, col, num) &&
        !usedInBox(matrix, row - (row % 3), col - (col % 3), num)
    );
}

void print_sgrid(int matrix[9][9]){

    for(int a=0;a<9;a++){

        for (int b=0;b<9;b++){
             printf("%d ",matrix[a][b]);
            if (b==2 || b==5) printf("| ");
        }
        printf("\n");
        if (a==2 || a==5) printf("------+-------+------\n");

    }
}

int solveSudoku(int matrix[9][9]) {
    int row = 0;
    int col = 0;
    int checkBlankSpaces = 0;

    /* verify if sudoku is already solved and if not solved,
    get next "blank" space position */
    for (row = 0; row < 9; row++) {
        for (col = 0; col < 9; col++) {
            if (matrix[row][col] == 0) {
                checkBlankSpaces = 1;
                break;
            }
        }
        if (checkBlankSpaces == 1) {
            break;
        }
    }
    // no more "blank" spaces means the puzzle is solved
    if (checkBlankSpaces == 0) return 1;

    // try to fill "blank" space with correct num
    for (int num = 1; num <= 9; num++) {
        /* isSafe checks that num isn't already present
        in the row, column, or 3x3 box (see below) */
        if (isSafe(matrix, row, col, num)) {
            matrix[row][col] = num;

            if (solveSudoku(matrix)) return 1;

            /* if num is placed in incorrect position,
            mark as "blank" again then backtrack with
            a different num */
            matrix[row][col] = 0;

        }
    }
    return 0;
}


int main (void){

if (solveSudoku(veryhard))
print_sgrid(veryhard);

    return 0;
}

Solution

  • This modification works for me, found no problems with it so far. Note that solution_cnt needs to be declared globally and cleared before you try to count solutions again.

    int count_solutions(int matrix[9][9]) {
        int row = 0;
        int col = 0;
        int checkBlankSpaces = 0;
    
        /* verify if sudoku is already solved and if not solved,
        get next "blank" space position */
        for (row = 0; row < 9; row++) {
            for (col = 0; col < 9; col++) {
                if (matrix[row][col] == 0) {
                    checkBlankSpaces = 1;
                    break;
                }
            }
            if (checkBlankSpaces == 1) {
                break;
            }
        }
        // no more "blank" spaces means the puzzle is solved
        if (checkBlankSpaces == 0){
            solution_cnt++;
            return solution_cnt;
        }
    
        // try to fill "blank" space with correct num
        for (int num = 1; num <= 9; num++) {
            /* isSafe checks that num isn't already present
            in the row, column, or 3x3 box (see below) */
            if (isSafe(matrix, row, col, num)) {
                matrix[row][col] = num;
    
                if(count_solutions(matrix)>1)return solution_cnt; //stop after a found amount of solutions
    
                /* if num is placed in incorrect position,
                mark as "blank" again then backtrack with
                a different num */
                matrix[row][col] = 0;
            }
        }
        return solution_cnt;
    }