手も足も出なかったためネット上で検索したところ
http://motonaga.hp.infoseek.co.jp/Sudoku/Sudoku.html
上記のページを見つけました。
しかし、私がポインタを使いこなせるレベルではなく、,main関数内の意味も分からなかったので、とりあえず真似だけでもと思い、他の関数を参考に以下のプログラムを作りました。
#include<stdio.h> #define BUFLEN 80 int initial[4][4],solve[4][4],x,y; int copy(void){//1~4以外の数値の時空欄(0)と置き直す関数 int i,j; for(i=0;i<4;i++){ for(j=0;j<4;j++){ if( initial[j]==1||initial[j]==2|| initial[j]==3||initial[j]==4 ){ solve[j]=initial[j]; }else{solve[j]=0; } } } return 0; } int print_answer(void){//答えの印字の関数 int i,j; for(i=0;i<4;i++){ for(j=0;j<4;j++){ printf("%2d",solve[j]);} printf("\n"); } printf("\n"); return 0; } int blank_search(){//空いた枡を見つける int i,j; for(i=0;i<4;i++){ for(j=0;j<4;j++) if (solve[j] == 0){ x=i; y=j; return 1; } } return 0; } int permit_puting(int k){ int i,j; for(i=0;i<4;i++){ /* 縦に同じ数はないか */ if(solve[y] == k){return 0;} } for(j=0;j<4;j++){/* 橫に同じ数はないか */ if(solve[x][j] == k){return 0;} } for(i=0;i<2;i++){/* blockに同じ数はないか */ for(j=0;j<2;j++){ if(solve[2*(x/2)+i][2*(y/2)+j]==k){return 0;} } } return 1; } int trial_error(int solve[4][4]){ int k; if (blank_search()==1){/* 盤に空いた枡(x,y)があるか */ for(k=1;k<=4;k++){ if(permit_puting(k)==1){/* 枡(x,y)にkを置けるか */ solve[x][y] = k; /* 置けるなら置く */ //print_answer(); trial_error(solve); /* 次を確かめる */ solve[x][y] = 0; /* 枡(x,y)にkを置けないとして別の置き方はないか */ } } }else{ print_answer(); } return 0; } int number_place(){//未完成(最終的にmainに記述された分岐のために0か1を返すように作る予定) copy(); trial_error(solve); return 0; } //以下は変更できない int main(void){ char buf[BUFLEN]; int i; for(i=0;i<4;i=i+1){ fgets(buf,BUFLEN, stdin); sscanf(buf,"%d %d %d %d", &initial[i][0],&initial[i][1], &initial[i][2],&initial[i][3]); } if (number_place()==1){ printf("solved.\n"); }else{ printf("not solved"); } return 0; }
コンパイルは可能です。またいくつかの問題も解くことはできるのですが、すべて空欄の場合解が1つしかでないなど欠陥があるようです。
trial_error内のprint_answerを実行させたところ、どうも再帰がうまくいってないような気がします。しかし改善方法も分からない状態です。
上記の通り、できればポインタは使いたくありませんが、ポインタを使わなければいけないようでしたら再考してみます。
Visual C++2008を使っています。
初投稿で至らない点があるとは思いますがよろしくお願いします。