您好,登錄后才能下訂單哦!
數(shù)獨(dú)游戲的解法:
先將數(shù)獨(dú)分為九個(gè)格子,用一個(gè)數(shù)組將每個(gè)小九宮格的候選數(shù)存放下來(lái),將候選數(shù)挨個(gè)放進(jìn)數(shù)獨(dú)里的空位,如果這一行和這一列都沒(méi)有這個(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號(hào)位置,然后將9插入
這個(gè)時(shí)候我們發(fā)現(xiàn)2不能放入剩下的兩格,我們就繼續(xù)撤回到1插入的時(shí)候,將2放入1號(hào)位置,然后挨個(gè)放入剩下的數(shù)
循環(huán)這一過(guò)程,直到數(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;//待測(cè)試的值的x坐標(biāo) int y;//待測(cè)試的值的y坐標(biāo) int p;//待測(cè)試的值的位置(1道9代表在九宮格里的位置) int n;//待測(cè)試的值 }A; A zhan[MAX];//存放每個(gè)放進(jìn)題目數(shù)組測(cè)試的數(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)九宮格測(cè)試的數(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)前測(cè)試數(shù)屬于小九宮格的位置 int t=-1;//棧的長(zhǎng)度 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)九宮格測(cè)試的數(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)九宮格測(cè)試的數(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;//重新獲取測(cè)試的值的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'; }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。