数独求解:用c++做一个数独求解的程序(附源代码和.exe文件)

        数独这个游戏大家都知道吧:玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫(3×3)内的数字均含1-9,不重复。

        为了更好的区分已填和未填的格子,未填的格子用0表示!!

1.输入

int a[11][11];
int alltheanswer;//所有的解
int wanttheanswer;//期望得到的解数
int main()
{
    printf("请输入9*9的数独:\n");
	for(int i=1; i<=9; i++)
		for(int j=1; j<=9; j++)
			scanf("%d",&a[i][j]);
	printf("请输入你期望得到的解数:\n");
	cin>>wanttheanswer;
}

2.检查每一行是否有重复

bool checkx(int x) {//x为第几行 
	for(int i=1; i<=9; i++) {
		if(a[x][i]==0)
			continue;
		for(int j=1; j<i; j++)
			if(a[x][i]==a[x][j])
				return false;
	}
	return true;
}

3.检查每一列是否有重复

bool checky(int y) { //y为第几列
	for(int i=1; i<=9; i++) {
		if(a[i][y]==0)
			continue;
		for(int j=1; j<i; j++)
			if(a[i][y]==a[j][y])
				return false;
	}
	return true;
}

4.检查每一个九宫格是否满足条件

bool jggfz(int x,int y) {//辅助判断 
	for(int i=x; i<x+3; i++) {
		for(int j=y; j<y+3; j++) {
			if(a[i][j]==0)
				continue;
			for(int ii=x; ii<i; ii++) {
				for(int jj=y; jj<y+3; jj++) {
					if(a[i][j]==a[ii][jj])
						return false;
				}
			}
		}
	}
	return true;
}
bool jgg() { //九宫格判断
	if(jggfz(1,1)==false)
		return false;
	if(jggfz(4,1)==false)
		return false;
	if(jggfz(7,1)==false)
		return false;
	if(jggfz(1,4)==false)
		return false;
	if(jggfz(4,4)==false)
		return false;
	if(jggfz(7,4)==false)
		return false;
	if(jggfz(1,7)==false)
		return false;
	if(jggfz(4,7)==false)
		return false;
	if(jggfz(7,7)==false)
		return false;
	return true;
}

5.进行搜索与回溯

void dfs(int na,int nb) { //第几行第几个
	if(na==10) {
		if(jgg()==true) {
			alltheanswer++;
			if(wanttheanswer>=alltheanswer) {
                printf("\n");
                printf("此题解%d\n",alltheanswer);
				for(int i=1; i<=9; i++) {
					for(int j=1; j<=9; j++) {
						if((i==4&&j==1)||(i==7&&j==1))
							printf(" -------------------\n");
						else if(j==4||j==7)
							printf("|");
                        printf("%2d",a[i][j]);
					}
					printf("\n");
				}
			}
			return;
		}
	}
	if(a[na][nb]!=0) {//特殊情况
		int nna=na,nnb=nb;
		if(nb==9)
			na++,nb=1;
		else
			nb++;
		dfs(na,nb);
		na=nna,nb=nnb;
		return;
	}
	for(int i=1; i<=9; i++) {
		a[na][nb]=i;
		if(checkx(na)==false||checky(nb)==false||jgg()==false) {
			a[na][nb]=0;
			continue;
		}
		int nna=na,nnb=nb;
		if(nb==9)
			na++,nb=1;
		else
			nb++;
		dfs(na,nb);
		na=nna,nb=nnb;
		a[nna][nnb]=0;
	}
}

【整体代码如下】


#include<bits/stdc++.h>//数独
using namespace std;
int a[11][11];
int alltheanswer;
int wanttheanswer;
bool checkx(int x) {//每行是否会重复
	for(int i=1; i<=9; i++) {
		if(a[x][i]==0)
			continue;
		for(int j=1; j<i; j++)
			if(a[x][i]==a[x][j])
				return false;
	}
	return true;
}
bool checky(int y) { //每列是否会重复
	for(int i=1; i<=9; i++) {
		if(a[i][y]==0)
			continue;
		for(int j=1; j<i; j++)
			if(a[i][y]==a[j][y])
				return false;
	}
	return true;
}
bool jggfz(int x,int y) {//根据jgg中输入的行和列,判断这个九宫格是否会发生冲突
	for(int i=x; i<x+3; i++) {
		for(int j=y; j<y+3; j++) {
			if(a[i][j]==0)
				continue;
			for(int ii=x; ii<i; ii++) {
				for(int jj=y; jj<y+3; jj++) {
					if(a[i][j]==a[ii][jj])
						return false;
				}
			}
		}
	}
	return true;
}
bool jgg() { //判断每个九宫格是否会发生冲突,具体看函数jggfz()
	if(jggfz(1,1)==false)
		return false;
	if(jggfz(4,1)==false)
		return false;
	if(jggfz(7,1)==false)
		return false;
	if(jggfz(1,4)==false)
		return false;
	if(jggfz(4,4)==false)
		return false;
	if(jggfz(7,4)==false)
		return false;
	if(jggfz(1,7)==false)
		return false;
	if(jggfz(4,7)==false)
		return false;
	if(jggfz(7,7)==false)
		return false;
	return true;
}
void dfs(int na,int nb) { //第几行第几个
	if(na==10) {
		if(jgg()==true) {
			alltheanswer++;
			if(wanttheanswer>=alltheanswer) {
				printf("\n");
				printf("此题解%d\n",alltheanswer);
				for(int i=1; i<=9; i++) {
					for(int j=1; j<=9; j++) {
						if((i==4&&j==1)||(i==7&&j==1))
							printf(" -------------------\n");
						else if(j==4||j==7)
							printf("|");
						printf("%2d",a[i][j]);
					}
					printf("\n");
				}
			}
			return;
		}
	}
	if(a[na][nb]!=0) {//这个位置的数已经填过了,直接填下一个数
		int nna=na,nnb=nb;
		if(nb==9)
			na++,nb=1;
		else
			nb++;
		dfs(na,nb);
		na=nna,nb=nnb;
		return;
	}
	for(int i=1; i<=9; i++) {//选择填什么数字:1~9
		a[na][nb]=i;
		if(checkx(na)==false||checky(nb)==false||jgg()==false) {//检查这一行,这一列,这一个九宫格填这个数字是否发生冲突
			a[na][nb]=0;
			continue;
		}
		int nna=na,nnb=nb;//保存开始的行,列
		//更新na,nb为下一个要填的位置
		//普通:nb+1
		//应为nb的范围为1~9所以当nb=9时就是要填下一行了,所以na+1
		if(nb==9)
			na++,nb=1;
		else
			nb++;
		dfs(na,nb);//填下一个数字
		na=nna,nb=nnb;//将开始的值返回
		a[nna][nnb]=0;
	}
}
int main() {
	printf("请输入9*9的数独:\n");
	for(int i=1; i<=9; i++)
		for(int j=1; j<=9; j++)
			scanf("%d",&a[i][j]);
	printf("请输入你期望得到的解数:\n");
	cin>>wanttheanswer;
	dfs(1,1);
	printf("此题所有解为:%d\n\n",alltheanswer);
	printf("--------------------------\n");
	printf("按Enter键退出\n");
	char a;//等待退出
	a=getchar();
	a=getchar();
	return 0;
}

代码测试:

 不方便执行c++代码的这边是.exe文件的下载地址:

链接:https://pan.baidu.com/s/1aA0ahZpZx2x0bVxjvSmL7g 
提取码:1234

(已经达到期望题解,答案不输出但一直输出换行的BUG已修复)

但是,感觉这个代码运行的速度太慢了,所以我优化了一下,上面的代码比较好理解

代码如下:

#include<bits/stdc++.h>//数独
using namespace std;
int a[11][11];
int b[11];//每行已知数最多
int bid[11];//b的id
int bbid;//bid第几个
int c[11];//每列已知数最多
int cid[11];//c的id
int ccid;//cid第几个
int maxx;
int alltheanswer;
int wanttheanswer;
bool checkx(int x) {//x为第几行
	for(int i=1; i<=9; i++) {
		if(a[x][i]==0)
			continue;
		for(int j=1; j<i; j++)
			if(a[x][i]==a[x][j])
				return false;
	}
	return true;
}
bool checky(int y) { //y为第几列
	for(int i=1; i<=9; i++) {
		if(a[i][y]==0)
			continue;
		for(int j=1; j<i; j++)
			if(a[i][y]==a[j][y])
				return false;
	}
	return true;
}
bool jggfz(int djgg) {
	int x,y;
	if(djgg==1)
		x=1,y=1;
	else if(djgg==2)
		x=1,y=4;
	else if(djgg==3)
		x=1,y=7;
	else if(djgg==4)
		x=4,y=1;
	else if(djgg==5)
		x=4,y=4;
	else if(djgg==6)
		x=4,y=7;
	else if(djgg==7)
		x=7,y=1;
	else if(djgg==8)
		x=7,y=4;
	else
		x=7,y=7;
	for(int k=1; k<=9; k++) {
		bool f=false;
		for(int i=x; i<x+3; i++) {
			for(int j=y; j<y+3; j++) {
				if(a[i][j]==0)
					continue;
				if(a[i][j]==k&&f==false)
					f=true;
				else if(a[i][j]==k)
					return false;
			}
		}
	}
	return true;
}
void dfs(int na,int nb) { //第几行第几个
	if(bbid==10) {
		alltheanswer++;
		if(wanttheanswer>=alltheanswer) {
			printf("\n");
			printf("此题解%d\n",alltheanswer);
			for(int i=1; i<=9; i++) {
				for(int j=1; j<=9; j++) {
					if((i==4&&j==1)||(i==7&&j==1))
						printf(" -------------------\n");
					else if(j==4||j==7)
						printf("|");
					printf("%2d",a[i][j]);
				}
				printf("\n");
			}
		}
		return;
	}
	if(a[na][nb]!=0) {
		int nna=na,nnb=nb,bbidd=bbid,ccidd=ccid;
		if(ccid==9)
			bbid++,ccid=1;
		else
			ccid++;
		dfs(bid[bbid],cid[ccid]);
		na=nna,nb=nnb,bbid=bbidd,ccid=ccidd;
		return;
	}
	for(int i=1; i<=9; i++) {
		a[na][nb]=i;
		int xx,yy;
		int djgg=(na-1)/3*3+(nb-1)/3+1;//第几个九宫格
		if(checkx(na)==false||checky(nb)==false||jggfz(djgg)==false) {
			a[na][nb]=0;
			continue;
		}
		int nna=na,nnb=nb,bbidd=bbid,ccidd=ccid;
		if(ccid==9)
			bbid++,ccid=1;
		else
			ccid++;
		dfs(bid[bbid],cid[ccid]);
		na=nna,nb=nnb,bbid=bbidd,ccid=ccidd;
		a[nna][nnb]=0;
	}
}
int main() {
	printf("请输入9*9的数独:\n");
	for(int i=1; i<=9; i++) {
		for(int j=1; j<=9; j++) {
			scanf("%d",&a[i][j]);
			if(a[i][j]!=0)
				b[i]++;
			if(a[j][i]!=0)
				c[i]++;
		}
	}

	//哪行已知数最多从哪行开始填,哪列已知数多从那列开始填
	for(int i=1; i<=9; i++)
		bid[i]=i,cid[i]=i;
	for(int i=1; i<=9; i++) {
		for(int j=1; j<=9-i; j++) {
			if(b[j]<b[j+1])
				swap(b[j],b[j+1]),swap(bid[j],bid[j+1]);
			if(c[j]<c[j+1])
				swap(c[j],c[j+1]),swap(cid[j],cid[j+1]);
		}
	}
	printf("请输入你期望得到的解数:\n");
	cin>>wanttheanswer;
	dfs(bid[++bbid],cid[++ccid]);
	printf("此题所有解为:%d\n\n",alltheanswer);
	printf("--------------------------\n");
	printf("按Enter键退出\n");
	char a;//等待退出
	a=getchar();
	a=getchar();
	return 0;
}

代码测试:

因为搜索的顺序不一样,所以解的输出顺序可能和第一个代码不一样。

下面是这个代码的.exe文件的下载地址:

链接:https://pan.baidu.com/s/1rWA2mxVqp4DxJp4lh73Z9w 
提取码:1234

  • 17
    点赞
  • 58
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
以下是一个简单的 C++ 数独求解程序,它使用递归算法和回溯技术: ```c++ #include<iostream> using namespace std; // 定义数独规格 #define N 9 // 打印数独矩阵 void print(int arr[N][N]) { for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { cout << arr[i][j] << " "; } cout << endl; } cout << endl; } // 检查数独是否符合规则 bool check(int arr[N][N], int row, int col, int num) { // 检查行 for (int i = 0; i < N; i++) { if (arr[row][i] == num) { return false; } } // 检查列 for (int i = 0; i < N; i++) { if (arr[i][col] == num) { return false; } } // 检查九宫格 int start_row = row - row % 3; int start_col = col - col % 3; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (arr[start_row + i][start_col + j] == num) { return false; } } } return true; } // 递归求解数独 bool solve(int arr[N][N], int row, int col) { // 检查是否已经填满 if (row == N - 1 && col == N) { return true; } // 到达行末,换到下一行 if (col == N) { row++; col = 0; } // 如果当前位置已经有数字,跳过 if (arr[row][col] > 0) { return solve(arr, row, col + 1); } // 尝试填入数字 for (int i = 1; i <= N; i++) { if (check(arr, row, col, i)) { arr[row][col] = i; if (solve(arr, row, col + 1)) { return true; } } arr[row][col] = 0; } return false; } int main() { // 初始化数独矩阵 int arr[N][N] = { {0, 0, 0, 0, 0, 0, 6, 8, 0}, {0, 0, 0, 0, 7, 3, 0, 0, 9}, {3, 0, 9, 0, 0, 0, 0, 4, 5}, {4, 9, 0, 0, 0, 0, 0, 0, 0}, {8, 0, 3, 0, 5, 0, 9, 0, 2}, {0, 0, 0, 0, 0, 0, 0, 3, 6}, {9, 6, 0, 0, 0, 0, 3, 0, 8}, {7, 0, 0, 6, 8, 0, 0, 0, 0}, {0, 2, 8, 0, 0, 0, 0, 0, 0} }; // 求解数独 if (solve(arr, 0, 0)) { // 打印解 print(arr); } else { cout << "无解!" << endl; } return 0; } ``` 这个程序使用了一个 `check` 函数来检查数独是否符合规则,一个 `solve` 函数来递归求解数独,以及一个 `main` 函数来初始化数独矩阵并调用 `solve` 函数。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值