Question
Answer and Explanation
A Sudoku solver in C typically uses backtracking to explore possible solutions. Size relationships (i.e., a number cannot be repeated in a row, column, or 3x3 box) are enforced at each step to prune the search space, dramatically improving efficiency. Here's a complete C code example:
This C code implements a Sudoku solver using a backtracking algorithm. It enforces the size relationships of Sudoku by checking for number conflicts in rows, columns, and 3x3 subgrids. The 'isSafe' function evaluates these constraints before attempting to place a number.
Here's the complete C code example:
#include <stdio.h>
#include <stdbool.h>
#define N 9
// Function to print the Sudoku grid
void printGrid(int grid[N][N]) {
for (int row = 0; row < N; row++) {
for (int col = 0; col < N; col++) {
printf("%d ", grid[row][col]);
}
printf("\\n");
}
}
// Function to check if it is safe to place a number in the grid
bool isSafe(int grid[N][N], int row, int col, int num) {
// Check if the number is already present in the row
for (int x = 0; x < N; x++)
if (grid[row][x] == num)
return false;
// Check if the number is already present in the column
for (int x = 0; x < N; x++)
if (grid[x][col] == num)
return false;
// Check if the number is already present in the 3x3 box
int startRow = row - row % 3;
int startCol = col - col % 3;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
if (grid[i + startRow][j + startCol] == num)
return false;
return true;
}
// Function to find an unassigned location
bool findUnassignedLocation(int grid[N][N], int row, int col) {
for (row = 0; row < N; (row)++)
for (col = 0; col < N; (col)++)
if (grid[row][col] == 0)
return true;
return false;
}
// Recursive function to solve Sudoku
bool solveSudoku(int grid[N][N]) {
int row, col;
// If there is no unassigned location, we are done
if (!findUnassignedLocation(grid, &row, &col))
return true; // Success!
// Consider digits 1 to 9
for (int num = 1; num <= N; num++) {
// If there is no conflict for digit num at row, col
if (isSafe(grid, row, col, num)) {
// Make tentative assignment
grid[row][col] = num;
// Return, if success
if (solveSudoku(grid))
return true;
// Failure, unmake & try again
grid[row][col] = 0;
}
}
// This triggers backtracking
return false; // This will trigger backtracking
}
// Main function to test the Sudoku solver
int main() {
int grid[N][N] = {
{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}
};
if (solveSudoku(grid)) {
printf("Solution:\\n");
printGrid(grid);
} else {
printf("No solution exists\\n");
}
return 0;
}
In this code:
- The isSafe
function verifies that placing a number violates no Sudoku rules.
- findUnassignedLocation
finds the next empty cell on the grid.
- solveSudoku
recursively attempts to solve the puzzle, backtracking when a dead-end is encountered.
This solution demonstrates a classic approach to solving Sudoku, leveraging backtracking and the inherent size relationships within the puzzle's constraints.