特に
/* 次の座標に何の値が入るか調べる */この辺りが。
int check_number;
for(check_number = 1; check_number <= GOBAN_N;) {
/* 再帰させる */
if(getans(ix, iy, check_number, konkai) == 0) {
/* 正解が見つかったとき */
return 0;
}
check_number++;
}
すっきりしないというか、2カ所でforループ使いたくねぇみたいな。。。
で、修正してみた。
/* バックトラック */こっちのほうが、読み飛ばし(既に値が入っていたときの処理)が複数回発生しないぶん、少し早い。
int check(int ix, int iy, struct GOBAN konkai){
int cx, cy;
int sx, sy;
int dupli;
int ret;
int number = 1;
while (konkai.number[ix][iy] != 0) {
/* マスに数字が入っている場合、次のマスを調べます */
ix++;
if(ix >= GOBAN_X) {
ix = 0;
iy++;
if(iy >= GOBAN_Y) {
/* 全てのマスが埋まった時、解答が見つかったと判断 */
for(cy = 0; cy < GOBAN_Y;) {
for(cx = 0; cx < GOBAN_X;) {
goban.number[cx][cy] = konkai.number[cx][cy];
cx++;
}
cy++;
}
return 0;
}
}
}
/* 全ての数を試してみる */
for(number = 1; number <= GOBAN_N;) {
// printf("%d,%d = %d\n", ix, iy, number);
dupli = 0;
/* タテの列で値が入るかをチェックする */
for (cy = 0; cy < GOBAN_Y; ++cy) {
if(konkai.number[ix][cy] == number) {
/* 既にチェックした数が存在した */
dupli = 1;
}
}
/* ヨコの列で値が入るかをチェックする */
for (cx = 0; cx < GOBAN_X; ++cx) {
if(konkai.number[cx][iy] == number) {
/* 既にチェックした数が存在した */
dupli = 1;
}
}
/* 3*3のマスで値が入るかをチェックする */
sx = ix - (ix % GOBAN_T);
sy = iy - (iy % GOBAN_T);
for(cx = 0; cx < GOBAN_T; ++cx) {
for(cy = 0; cy < GOBAN_T; ++cy) {
if(konkai.number[sx + cx][sy + cy] == number) {
/* 既にチェックした数が存在した */
dupli = 1;
}
}
}
if(dupli == 0) {
/* 値が入る事が判ったので値を入れてみる */
konkai.number[ix][iy] = number;
if((ret = check(ix, iy, konkai)) == 0) {
return 0;
}
}
number++;
}
/* 1〜9までそれも答えでは無い時 */
return -1;
}
なんとなくスッキリした。。。
sudoku.tar.gz
多分、普通の環境ならmakeすれば動くと思う。
コメント