代码解决数独问题

来源:https://blog.csdn.net/FelikZhang/article/details/104367512?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-0-104367512-blog-117999902.pc_relevant_3mothn_strategy_and_data_recovery&spm=1001.2101.3001.4242.1&utm_relevant_index=2

#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值