#include <stdio.h>
#include <stdlib.h>
#define N 3
#define M 9
/*******************************************定义全局变量***************************************************/
int x[M][M]={
{0,8,0, 0,1,0, 0,0,5},
{0,0,1, 9,0,0, 4,2,0},
{9,2,0, 0,0,0, 0,0,0},
{0,6,0, 0,0,7, 0,3,0},
{0,3,7, 0,0,0, 0,0,2},
{0,0,0, 1,5,0, 0,0,0},
{0,4,5, 3,0,6, 0,0,9},
{2,0,0, 0,0,0, 0,0,8},
{3,0,0, 0,0,9, 0,0,0},
};
/* 结果:
4 2 3 7 6 9 5 1 8
5 7 6 4 8 1 3 2 9
9 8 1 5 3 2 7 6 4
8 3 5 6 7 4 1 9 2
1 9 7 2 5 8 6 4 3
2 6 4 9 1 3 8 5 7
6 5 9 8 4 7 2 3 1
7 1 2 3 9 6 4 8 5
3 4 8 1 2 5 9 7 6
*/
/*---------------------------------------------------------------------------------------------------------*/
/*
//int x[][]={
// {0,6,0,5,9,3,0,0,0},
// {9,0,1,0,0,0,5,0,0},
// {0,3,0,4,0,0,0,9,0},
// {1,0,8,0,2,0,0,0,4},
// {4,0,0,3,0,9,0,0,1},
// {2,0,0,0,1,0,6,0,9},
// {0,8,0,0,0,6,0,2,0},
// {0,0,4,0,0,0,8,0,7},
// {0,0,0,7,8,5,0,1,0},
//};*/
/* 结果:
7 6 2 5 9 3 1 4 8
9 4 1 2 7 8 5 3 6
8 3 5 4 6 1 7 9 2
1 9 8 6 2 7 3 5 4
4 7 6 3 5 9 2 8 1
2 5 3 8 1 4 6 7 9
3 8 7 1 4 6 9 2 5
5 1 4 9 3 2 8 6 7
6 2 9 7 8 5 4 1 3
*/
/******************************************* 函数声明 ***************************************************/
/*//解决问题最主要的递归函数,递归访问大的9*9矩阵中的每一个小格,对待填空格(二维数组x中值为零的格子)进行填值操作。*/
void Solve(int r, int c);
/*//以下3个函数为Solve运行过程中调用的判断函数,具体在下面有注释。 */
int checkedbox(int r);
int checked(int r, int c, int num);
int* getData(int r, int c,int *data);
/*//输出最终计算结果的函数*/
void show(void);
/******************************************* 函数定义 ***************************************************/
void Solve(int r, int c)
{
int i;
/* //(一)
/* //如果填的行号增加到了9,表示已经填完了整个数独空格(x二维数组行列的下标范围均为 0-8),打印结果即可*/
if (r == M) {
show();
return; /* //此处的return返回表示已经填完了整个数独空格,接下来会逐步返回到主函数 */
}
/* //(二) */
/* //在填写第3、6行开头数字的时,检查上边的三行的方块里是不是有重复的数字*/
if (c == 0 && (r == N || r == N*2)) {
if (checkedbox(r) == 0) { /* // checkedbox()返回0表示小九宫格中出现了重复数字,说明之前的填写有误,则需要返回之前的填写试探中。 */
return; /* //这里的return会返回到第四个if中的某次循环中 */
}
}
/* //(三) */
/* //填到某行最后一个元素时,要转到下一行开头去*/
if (c == M) {
Solve(r+1, 0);
return;
}
/* //(四) */
/* //当前的坐标是0的时候才开始循环填写,否则跳过去填写下一个数字*/
if (x[r][c] == 0) {
for (i = 1; i <= M; i++) { /*//对于每一个待填写的空格,循环1-9进行试探*/
if (checked(r,c,i) == 1) {
x[r][c]=i;
Solve(r, c+1);
x[r][c]=0;
}
}
}
/* 如果上面的四个情况都不是。则正常地填该行的下一个元素,即行号不动,列号往前走一个。即Solve(r, c+1);
上面的四个情况是指:
1.既没有填写或处理完整个数独表
2.也不是刚填写或处理完了3个并列的小九宫格
3.也没有填写或处理到某行最后一个元素
4.此处坐标也不是零,即无需填写或处理
*/
else{
Solve(r, c+1);
}
}
/**
* 得到指定小九宫格中的九个数据,存入data中并返回data指针
* @param r 行号,可能取值为3,6
* @param c 列号,可能取值为0,3,6
* @return 判断结果,0表示小九宫格中有重复数字。1表示小九宫格中无重复数字。
*/
int checkedbox(int r) {
int i,j,c;
int *data = malloc(sizeof(int)*M);
for (c = 0; c < M; c+=N) {/* //循环三次,分别是c=0,3,6。对应循环大矩阵中9个3*3的小九宫格*/
data = getData(r,c,data); /* //得到小九宫格中的九个数据,存入全局变量数组data中 */
for(i = 0; i < M-1 ; i++) {
for(j = i+1 ; j < M ; j++) {
if(data[i] == data[j]) { /*//循环成立表示有重复数字*/
return 0; /* //有重复数字,返回0。*/
}
}
}
}
free(data); /*//函数执行结束,返回判断结果以前,释放指针malloc的空间。 */
return 1; /*//该函数能运行至此还没有结束返回,表示并列的三个小九宫格中,填入的均是1-9,没有重复数字,故返回1。*/
}
/**
* 得到指定小九宫格中的九个数据,存入data中并返回data指针
* @param r 行号,可能取值为3,6
* @param c 列号,可能取值为0,3,6
* @return data指针(数组)
*/
int* getData(int r, int c,int *data){
int i,j,k = 0;
for (i = r-N; i < r ; i++) {
for(j = c; j < c+N ; j++){
data[k++] = x[i][j];
}
}
return data;
}
/**
* 判断某个待填位置所在的行和列是否有某个数字
* @param r 待填位置的行号
* @param c 待填位置的列号
* @param num 需要比较的待填数字
* @return 返回0:有重复数字,x[r][c]位置不能填num
*/
int checked(int r, int c, int num) {
int j = 0,flag = 1;
for (j = 0; j < M; j++) {
if (x[j][c]==num || x[r][j]==num) {
flag = 0;
}
}
return flag;
}
/*//输出运算结果*/
void show(void) {
int i,j;
for (i = 0; i < M; i++) {
for (j = 0; j < M; j++) {
printf("%d ",x[i][j]);
}
printf("\n");
}
printf("\n");
}
int main(void)
{
Solve(0,0);
return 0;
}
代码解决数独问题
最新推荐文章于 2024-07-19 15:45:46 发布