I have to implement the solve method recursive in the sudoku.c for university.
I tried hard but all my implementations did not work.
I am an absolute newbie in programming c and so I despair on working with this Sudoku backtracking algorithm.
Can somebody help me?
The solve method was empty, so everything what's inside this method are just tries from me.
sudoku.h
#ifndef _SUDOKU_H_
#define _SUDOKU_H_
#define SIZE 9
#define SQRT_SIZE 3
void init(int begin[SIZE][SIZE]);
void print();
int checkValueInField(int value, int row, int col);
int setValueInField(int value, int row, int col);
int removeValueFromField(int row, int col);
int getValueFromField(int row, int col);
int solve(int row, int col);
#endif /* _SUDOKU_H_ */
sudoku.c
#include "sudoku.h"
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#define SIZE 9
#define SQRT_SIZE 3
int field[SIZE][SIZE];
int initial[SIZE][SIZE];
/* Initializes the sudoku array.
* The field initial keeps the original start value for
* figuring out if a value is fixed or can be changed. */
void init(int begin[SIZE][SIZE]) {
memcpy(field, begin, SIZE * SIZE * sizeof(int));
memcpy(initial, begin, SIZE * SIZE * sizeof(int));
}
/* really pretty prints the sudoku array */
void print() {
int row, col;
// print the first line
printf("||");
for (col = 0; col < SIZE - 1; col++) {
if (col % SQRT_SIZE == SQRT_SIZE - 1)
printf("===++");
else
printf("===+");
}
printf("===||\n");
// loop through all rows of the array
for (row = 0; row < SIZE; row++) {
// print the line with field values
for (col = 0; col < SIZE; col++) {
if (col % SQRT_SIZE == 0)
printf("|| ");
else
printf("| ");
if (field[row][col] == 0)
printf(" ");
else
printf("%d ", field[row][col]);
}
// print the separation line;
// depending on the result of the modulo operation
// print a single or double line
printf("||\n||");
if (row % SQRT_SIZE == SQRT_SIZE - 1) {
for (col = 0; col < SIZE - 1; col++) {
if (col % SQRT_SIZE == SQRT_SIZE - 1)
printf("===++");
else
printf("===+");
}
printf("===||\n");
}
else {
for (col = 0; col < SIZE - 1; col++) {
if (col % SQRT_SIZE == SQRT_SIZE - 1)
printf("---++");
else
printf("---+");
}
printf("---||\n");
}
}
}
/* Checks if the value is valid and can be set into the field.
* The function returns false if the value is already present or
* has been one of the initial values. */
int checkValueInField(int value, int row, int col) {
int i, r, c;
int squareRow;
int squareCol;
// checks for initial values
if (initial[row][col] != 0) {
if (initial[row][col] == value)
return 1;
else
return 0;
}
// check horizontally
for (i = 0; i < SIZE; i++) {
if (field[row][i] == value) return 0;
}
// check vertically
for (i = 0; i < SIZE; i++) {
if (field[i][col] == value) return 0;
}
// check square
squareRow = row / SQRT_SIZE;
squareCol = col / SQRT_SIZE;
for (r = squareRow * SQRT_SIZE; r < squareRow * SQRT_SIZE + SQRT_SIZE; r++) {
for (c = squareCol * SQRT_SIZE; c < squareCol * SQRT_SIZE + SQRT_SIZE; c++) {
if (field[r][c] == value) return 0;
}
}
return 1;
}
/* Set a value in the sudoku field if the field is empty.
* The method returns false if the field contains a fixed number. */
int setValueInField(int value, int row, int col) {
if (initial[row][col] == 0) {
field[row][col] = value;
return 1;
}
else if (initial[row][col] == value)
return 1;
return 0;
}
/* Removes a value in the sudoku field if it doesn't contain an initial value.
* The method returns false if the field contains a fixed number and cannot be
* removed. */
int removeValueFromField(int row, int col) {
if (initial[row][col] == 0) {
field[row][col] = 0;
return 1;
}
return 0;
}
/* Returns the value in the field */
int getValueFromField(int row, int col) {
return field[row][col];
}
/* Return true if you've found a valid solution for the sudoku. Use the
* return value to abort the backtracking algorithm if you've found the
* first solution, otherwise you would search for a possible solution. */
int solve(int row, int col) {
/* Implement a backtracking for solving the sudoku */
for (int i = 1; i <= 9; i++) {
if ((checkValueInField(i, row, col)) == 1) {
setValueInField(i, row, col);
}
solve(row, col + 1);
solve(row + 1, col);
}
return 0;
}
main.c
#include <stdio.h>
#include "sudoku.h"
int main(int argc, char * const argv[]) {
int initial[SIZE][SIZE] = {
{0, 1, 0, 0, 0, 9, 0, 5, 0},
{0, 9, 0, 0, 0, 0, 4, 8, 0},
{0, 6, 0, 1, 0, 4, 0, 0, 0},
{0, 0, 5, 0, 0, 0, 9, 3, 0},
{0, 0, 0, 7, 0, 2, 0, 0, 0},
{0, 2, 1, 0, 0, 0, 8, 0, 0},
{4, 0, 0, 0, 8, 0, 6, 0, 9},
{0, 0, 0, 0, 6, 0, 5, 0, 3},
{2, 0, 0, 0, 3, 0, 0, 0, 0},
};
init(initial);
print();
solve(0, 0);
print();
return 0;
}
You might want to look at what is a backtracking algorithm
Your solve would be solving one position (tracked by row and col ) at a time and recursively check solve the next position.
So your solve function should at least walk through the grid
int solve(int row, int col) {
// solve next column in the current row
return solve(row, col + 1);
}
As you can see the issue become that the col would be growing indefinitely without checking other rows. (by the way the first element of an array in C have an index of 0 )
So we need to move to the other row once we reach the end of this one ( Assuming that END_COLUMN_INDEX
contains the index of the last column)
if(col == END_COLUMN_INDEX) { // we just reached the end of the current row
return solve(row+1, 0); // solve the beginning of the next row
}
Now your solving will automatically move to the next row, but what about when we reach the last row ( Assuming that END_ROW_INDEX
contains the index of the row column)
if((col == END_COLUMN_INDEX) && (row == END_ROW_INDEX)) { // we reached the end of the grid meaning that we might have successfully solved the whole grid
return 1; // return true
}
Now walking throught what should be implemented as this point.
solve(0,0) -> solve(0,1)
solve(0,1) -> solve(0,2)
solve(0,2) -> solve(0,3)
...
solve(0,END_COLUMN_INDEX - 1) -> solve(0, END_COLUMN_INDEX)
solve(0, END_COLUMN_INDEX) -> solve(1, 0)
...
...
solve(END_ROW_INDEX , END_COLUMN_INDEX - 1) -> solve(END_ROW_INDEX , END_COLUMN_INDEX) -> return true
(the true value is returned through each upper level of recursion)
We are now recursively moving through the grid
for each cell you need to check
solve
the next cell) checkValueInField
): setValueInField
) and try to solve
the next cell that means that the upper level of recursion is wrong, so the solve function will return false
to communicate that the value in the previous cell is wrong ( the upper layer would be at step 1 or 3 )
test what solve
-ing the next cell returned ( at step 1 or 3 )
solve
able, we might want to try other values (backtracking ). when returning false
to the upper value of recursion you must not forget to restore the value of the current cell to its original value ( removeValueFromField
).
At this point you should have all the guides to resolve your issue and write your recursive sudoku solving function.
Additionally internet is filled with great example of sudoku solving code.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.