C語言數(shù)獨(dú)游戲的求解方法
數(shù)獨(dú)游戲的解法:
先將數(shù)獨(dú)分為九個(gè)格子,用一個(gè)數(shù)組將每個(gè)小九宮格的候選數(shù)存放下來,將候選數(shù)挨個(gè)放進(jìn)數(shù)獨(dú)里的空位,如果這一行和這一列都沒有這個(gè)數(shù)字,繼續(xù)放入下一個(gè),如果不能放入的話就回到上一步繼續(xù)嘗試,直到成功求出數(shù)獨(dú)的解為止;

比如這個(gè)數(shù)獨(dú)第一個(gè)九宮格的候選數(shù)就有1,2,7,8,9,我們需要從1開始放入第一個(gè)格子挨個(gè)嘗試直到8的時(shí)候發(fā)現(xiàn)剩下的兩個(gè)格子都不能放入

這個(gè)時(shí)候我們就要撤回上一個(gè)插入的7,發(fā)現(xiàn)8仍然不能放入,就繼續(xù)撤回2,發(fā)現(xiàn)8可以放入,就將8放入3號位置,然后將9插入

這個(gè)時(shí)候我們發(fā)現(xiàn)2不能放入剩下的兩格,我們就繼續(xù)撤回到1插入的時(shí)候,將2放入1號位置,然后挨個(gè)放入剩下的數(shù)

循環(huán)這一過程,直到數(shù)獨(dú)求出解為止;
這個(gè)方法比較容易想到,操作也比較容易實(shí)現(xiàn)
下面是代碼
代碼大多數(shù)都寫了備注便于理解
題目需要的1000道題放在下面了,將這1000個(gè)txt文件拷到EXE文件同一目錄就可以了
題目鏈接:數(shù)獨(dú)題目
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 81
typedef struct asd{
int x;//待測試的值的x坐標(biāo)
int y;//待測試的值的y坐標(biāo)
int p;//待測試的值的位置(1道9代表在九宮格里的位置)
int n;//待測試的值
}A;
A zhan[MAX];//存放每個(gè)放進(jìn)題目數(shù)組測試的數(shù)據(jù)
void kongque(int queshi[9][9],int aa[9][9]);//函數(shù)將候選數(shù)數(shù)組里去除題目中有的數(shù)字
void shuchu(int aa[9][9],int q);//輸出整個(gè)數(shù)組到文件中
int end(int aa[9][9]); //判斷是否結(jié)束
int next(int queshi[9][9],int m,int n,int *x,int *y,int aa[9][9]);//查找下一個(gè)應(yīng)該放進(jìn)九宮格測試的數(shù)據(jù)
int chazhao(int aa[9][9],int m,int n,int num);//查找同一行同一列是否有相同的值
int nfrz(int queshi[9][9],int aa[9][9],int m,int n,int *p);//判斷是否滿足入棧條件(就是當(dāng)前值是否可以插入九宮格)
int rz(int *t,int x,int y,int p,int num);//入棧操作
int cz(int *t,int *x,int *y,int *p,int *num);//出棧操作
void aaaa(char aa[10],int a);//計(jì)算題目文件的文件名
void bbbb(char aa[10],int a);//計(jì)算答案文件的文件名
int main(){
int i;//記錄該調(diào)用哪道題
for(i=0;i<1000;i++){
int aa[9][9],j,k;//aa數(shù)組存放的是題目數(shù)獨(dú)
int queshi[9][9];//存放的是每個(gè)九宮格的待選數(shù)
int end=0;//判斷循環(huán)結(jié)束條件
int h=0,l=0,p=1;//h是候選數(shù)的行坐標(biāo),l是候選數(shù)的列坐標(biāo),p代表當(dāng)前測試數(shù)屬于小九宮格的位置
int t=-1;//棧的長度
int s=0,num;
FILE *u;
char qwe[10];
for(j=0;j<9;j++)//將數(shù)組置為每行都是(1到9)
for(k=0;k<9;k++)
queshi[j][k]=k+1;
aaaa(qwe,i);
u=fopen(qwe,"r");
for(j=0;j<9;j++){//讀入題目
for(k=0;k<9;k++){
fscanf(u,"%d",&aa[j][k]);
}
}
fclose(u);
memset(zhan,0,sizeof(zhan));//將棧的數(shù)據(jù)全部置為0
kongque(queshi,aa);
while(end!=1){//開始求解
s=next(queshi,h,l,&h,&l,aa);//查找下一個(gè)應(yīng)該放進(jìn)九宮格測試的數(shù)據(jù)
if(s==0){//如果找到則進(jìn)入下一層
s=nfrz(queshi,aa,h,l,&p);//判斷能否插入數(shù)獨(dú)里
if(s==0){//如果可以則將插入的數(shù)據(jù)存放到棧里(入棧)
s=rz(&t,h,l,p,queshi[h][l]);
if(s==0){ //如果入棧成功則寫入數(shù)獨(dú)
aa[h/3*3+(p-1)/3][h%3*3+(p-1)%3]=queshi[h][l];
l++;//待選數(shù)跳到下一個(gè)
p=1;//重新從第一個(gè)小格子開始判斷是否插入
}
else{
end=1;//循環(huán)結(jié)束
}
}
else{
s=cz(&t,&h,&l,&p,&num);
if(s==0){//如果出棧成功則擦除插入的數(shù)據(jù)
aa[h/3*3+(p-1)/3][h%3*3+(p-1)%3]=0;
p++;
}
else
end=1;
}
}
else if(s==-1){
shuchu(aa,i);//輸出求解完畢的數(shù)獨(dú)
end=1;
}
else{
printf("發(fā)生未知錯(cuò)誤");
end=1;
}
}
}
return 0;
}
//函數(shù)將候選數(shù)數(shù)組里去除題目中有的數(shù)字
void kongque(int queshi[9][9],int aa[9][9]){
int i,j,x,y;
for(i=0;i<j;i++){
for(j=0;j<9;j++){
if(aa[i][j]){
x=i/3*3+j/3;//數(shù)獨(dú)數(shù)組和候選數(shù)數(shù)組的坐標(biāo)轉(zhuǎn)換
y=aa[i][j]-1;
queshi[x][y]=0;
}
}
}
}
//輸出整個(gè)數(shù)組到文件中
void shuchu(int aa[9][9],int q){
int i,j;
FILE *p;
char qq[10];
bbbb(qq,q);
p=fopen(qq,"w");
for(i=0;i<9;i++){
for(j=0;j<9;j++){
fprintf(p,"%d ",aa[i][j]);
}
fprintf(p,"\n");
}
fclose(p);
}
//判斷是否結(jié)束
int end(int aa[9][9]){
int i,j,num=0;
for(i=0;i<9;i++){
num=0;
for(j=0;j<0;j++){
num+=aa[i][j];//檢查每一行是否為1到9
}
if(num!=45)
return -1;
}
for(j=0;j<9;j++){//檢查每一列是否為1到9
num=0;
for(i=0;i<9;i++){
num+=aa[i][j];
}
if(num!=45)
return -1;
}
return 0;
}
//查找下一個(gè)應(yīng)該放進(jìn)九宮格測試的數(shù)據(jù)
int next(int queshi[9][9],int m,int n,int *x,int *y,int aa[9][9]){
int qqq=0;
if(n>8){//如果當(dāng)前小九宮格填寫完畢則進(jìn)入下一個(gè)九宮格
n=0;
m++;
}
if(m>8){
qqq=end(aa);//判斷是否結(jié)束
if(qqq!=0)
return -1;
else
return 1;
}
while(queshi[m][n]==0){
if(n<8)
n++;
else{
n=0;
m++;
if(m>8){
qqq=end(aa);
if(qqq!=0)
return -1;
else
return 1;
}
}
}
*x=m;//重新獲取測試的值的x坐標(biāo)和y坐標(biāo)
*y=n;
return 0;
}
//查找同一行同一列是否有相同的值
int chazhao(int aa[9][9],int m,int n,int num){
int i;
for(i=0;i<9;i++){//查找行
if(aa[m][i]==num)
return -1;
}
for(i=0;i<9;i++){//查找列
if(aa[i][n]==num)
return -1;
}
return 0;
}
//判斷是否滿足入棧條件(就是當(dāng)前值是否可以插入九宮格)
int nfrz(int queshi[9][9],int aa[9][9],int m,int n,int *p){
int s=*p;
int i,t1,t2,num;
num=queshi[m][n];
for(i=s;i<10;i++){
t1=(m/3)*3+(s-1)/3;
t2=(m%3)*3+(s-1)%3;
if(aa[t1][t2]!=0){
s++;
continue;
}
if(chazhao(aa,t1,t2,num)!=0){
s++;
continue;
}
else{
*p=s;
return 0;
}
}
return -1;
}
//入棧操作
int rz(int *t,int x,int y,int p,int num){
if(*t>=MAX){
return -1;
}
else{
(*t)++;
zhan[*t].x=x;
zhan[*t].y=y;
zhan[*t].p=p;
zhan[*t].n=num;
return 0;
}
}
//出棧操作
int cz(int *t,int *x,int *y,int *p,int *num){
if(*t==-1){
return -1;
}
else{
*x=zhan[*t].x;
*y=zhan[*t].y;
*p=zhan[*t].p;
*num=zhan[*t].n;
(*t)--;
return 0;
}
}
//計(jì)算題目文件的文件名
void aaaa(char aa[10],int a){
if(a>=0&&a<10){
aa[0]='0';
aa[1]='0';
aa[2]='0';
aa[3]=a+'0';
}
else if(a<100){
aa[0]='0';
aa[1]='0';
aa[2]=a/10+'0';
aa[3]=a%10+'0';
}
else if(a<1000){
aa[0]='0';
aa[1]=a/100+'0';
aa[2]=a/10%10+'0';
aa[3]=a%10+'0';
}
aa[4]='.';
aa[5]='t';
aa[6]='x';
aa[7]='t';
aa[8]='\0';
}
//計(jì)算答案文件的文件名
void bbbb(char aa[10],int a){
if(a>=0&&a<10){
aa[0]='a';
aa[1]='0';
aa[2]='0';
aa[3]=a+'0';
}
else if(a<100){
aa[0]='a';
aa[1]='0';
aa[2]=a/10+'0';
aa[3]=a%10+'0';
}
else if(a<1000){
aa[0]='a';
aa[1]=a/100+'0';
aa[2]=a/10%10+'0';
aa[3]=a%10+'0';
}
aa[4]='.';
aa[5]='t';
aa[6]='x';
aa[7]='t';
aa[8]='\0';
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C語言實(shí)現(xiàn)將字符串轉(zhuǎn)換為數(shù)字的方法
這篇文章主要介紹了C語言實(shí)現(xiàn)將字符串轉(zhuǎn)換為數(shù)字的方法,涉及系統(tǒng)函數(shù)atoi()函數(shù)的使用技巧,需要的朋友可以參考下2014-12-12
VC++植物大戰(zhàn)僵尸中文版修改器實(shí)現(xiàn)代碼
這篇文章主要介紹了VC++植物大戰(zhàn)僵尸中文版修改器實(shí)現(xiàn)代碼,可實(shí)現(xiàn)植物大戰(zhàn)僵尸中的無限陽光與無冷卻時(shí)間功能,需要的朋友可以參考下2015-04-04
淺析VSCode launch.json中的各種替換變量的意思 ${workspaceFolder} ${file} $
這篇文章主要介紹了VSCode launch.json中的各種替換變量的意思 ${workspaceFolder} ${file} ${fileBasename} ${fileDirname}等,非常不錯(cuò)具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03
C++實(shí)現(xiàn)簡單的信息管理系統(tǒng)
這篇文章主要為大家介紹了C++實(shí)現(xiàn)簡單的信息管理系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-04-04
如何用C語言、Python實(shí)現(xiàn)棧及典型應(yīng)用
本文先通過實(shí)例分別介紹了如何用C語言、Python實(shí)現(xiàn)棧,后又介紹棧的典型應(yīng)用,對大家學(xué)習(xí)棧很有借鑒參考價(jià)值,下面一起來看看吧。2016-08-08
C++?opencv實(shí)現(xiàn)在圖片上畫一條線示例代碼
這篇文章主要為大家介紹了C++?opencv實(shí)現(xiàn)在圖片上畫一條線的示例代碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05

