手も足も出なかったためネット上で検索したところ
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を使っています。
初投稿で至らない点があるとは思いますがよろしくお願いします。