数独のアルゴリズム
Posted: 2016年11月29日(火) 12:35
はじめまして今c言語を使って数独を自動で回答するプログラムを作成しています。あるアルゴリズムの作成で困っています。
たとえば、以下のようなボックス(3*3のスペース)があったとします
-----
|870|
|490|
|530|
-----
このようになっていた場合、このボックス以外の空欄(0=空欄)の列にあるマスには[1,2,6]を入れることができません。
・・・このようなアルゴリズムを実装したいのですがどのようにすればいいかご教授していただきたいです。
下記は今まで出作成したプログラムです。
たとえば、以下のようなボックス(3*3のスペース)があったとします
-----
|870|
|490|
|530|
-----
このようになっていた場合、このボックス以外の空欄(0=空欄)の列にあるマスには[1,2,6]を入れることができません。
・・・このようなアルゴリズムを実装したいのですがどのようにすればいいかご教授していただきたいです。
下記は今まで出作成したプログラムです。
#include<stdio.h>
#include <windows.h>
#include <time.h>
void yokocheck(int suudoku[10][10][10]);
void tatecheck(int suudoku[10][10][10]);
void boxcheck(int suudoku[10][10][10]);
void botticheck(int suudoku[10][10][10]);
void show(int suudoku[10][10][10]);
void oneboxonespace(int suudoku[10][10][10]);
void suudokusyokika(int suudoku[10][10][10]);
int main(void){
int i,j,k;
int suudoku[10][10][10];
int yf[81],xf[81],syokiti[81];
suudokusyokika(suudoku);
i=0;
while(1){
/* printf("初期値(y,x,入れたい値)を入力して下さい\n");
printf("入力が終了したら -1 と入力して下さい\n");*/
scanf("%d %d %d",&yf[i],&xf[i],&syokiti[i]);
if(yf[i]==-1) break;
i++;
}
clock_t start,end;
start = clock();
for(j=0;j<i;j++) suudoku[yf[j]][xf[j]][0]=syokiti[j];
for(i=0;i<10;i++){ /*このfor文はいずれ「答えが出るまで」ループする予定です*/
show(suudoku); //現在の確定している数字を表示
yokocheck(suudoku); //全てのx軸の候補を削除
tatecheck(suudoku); //全てのy軸の候補を削除
boxcheck(suudoku); //box内に確定している数字がある時、ボックス内の他のマスの候補を削減する
botticheck(suudoku); //一つのマスに入れることができる数字の候補が一つしかないとき、確定させる
oneboxonespace(suudoku); //一ボックスに一マスのみ入れることができる数字があるとき、確定させる
for(j=4;j<=6;j++){
for(k=7;k<=9;k++){
printf("%d ",suudoku[j][k][9]);
}
}
printf("\n");
}
printf("\n");
end = clock();
printf("%.2f秒かかりました\n",(double)(end-start)/CLOCKS_PER_SEC);
return 0;
}
void yokocheck(int suudoku[10][10][10]){
int i,j,k;
for(i=1;i<=9;i++){
for(j=1;j<=9;j++){
if(suudoku[i][j][0]!=0){
for(k=0;k<=9;k++){
suudoku[i][k][suudoku[i][j][0]]=0;
}
}
}
}
}
void tatecheck(int suudoku[10][10][10]){
int i,j,k;
for(j=1;j<=9;j++){
for(i=1;i<=9;i++){
if(suudoku[i][j][0]!=0){
for(k=0;k<=9;k++){
suudoku[k][j][suudoku[i][j][0]]=0;
}
}
}
}
}
void boxcheck(int suudoku[10][10][10]){
int i,j,k,l,xziku,yziku;
for(i=1;i<=9;i++){
for(j=1;j<=9;j++){
if(suudoku[i][j][0]>=1){
if(i<=3) yziku=1;
else if(i<=6) yziku=4;
else yziku=7;
if(j<=3) xziku=1;
else if(j<=6) xziku=4;
else xziku=7;
for(k=yziku;k<=yziku+2;k++){
for(l=xziku;l<=xziku+2;l++){
suudoku[k][l][suudoku[i][j][0]]=0;
}
}
}
}
}
}
void botticheck(int suudoku[10][10][10]){
int i,j,k,cnt;
for(i=1;i<=9;i++)
for(j=1;j<=9;j++){
if(suudoku[i][j][0]!=0);
else {
cnt=0;
for(k=1;k<=9;k++) if(suudoku[i][j][k]==1) cnt++;
if(cnt==1) {
for(k=1;k<=9;k++) if(suudoku[i][j][k]==1) suudoku[i][j][0]=k;
}
}
}
}
void show(int suudoku[10][10][10]){
int i,j;
printf("\n");
for(i=1;i<=9;i++){
for(j=1;j<=9;j++){
printf("%d",suudoku[i][j][0]);
if(j%3==0 && j!=9) printf("|");
}
printf("\n");
if(i%3==0 && i!=9) printf("------------\n");
}
printf("\n");
}
void oneboxonespace(int suudoku[10][10][10]){
int i,j,k,l,m,xziku,yziku,cnt[10];
for(i=1;i<=9;i+=3){
for(j=1;j<=9;j+=3){
for(l=1;l<=9;l++) cnt[l]=0;
for(m=1;m<=9;m++) { //調べたい数字
for(k=i;k<=i+2;k++){ //1ボックスの中で調べる
for(l=j;l<=j+2;l++){
if(suudoku[k][l][0]==m) {
cnt[m]=-1;
break;
}
else if(suudoku[k][l][m]==1 && suudoku[k][l][0]==0) cnt[m]++;
}
if(cnt[m]==-1) break;
}
if(cnt[m]==1){
for(k=i;k<=i+2;k++){ //1ボックスの中で調べる
for(l=j;l<=j+2;l++){
if(suudoku[k][l][m]==1 && suudoku[k][l][0]==0) suudoku[k][l][0]=m;
}
}
}
}
}
}
}
void suudokusyokika(int suudoku[10][10][10]){
int i,j,k;
for(i=0;i<=9;i++){
for(j=0;j<=9;j++){
suudoku[i][j][0]=0;
for(k=1;k<=9;k++)suudoku[i][j][k]=1;
}
}
}