はじめまして!
C言語初心者です。
今、数独の問題をつくるプログラムをC言語で作っています。
数独については(http://ja.wikipedia.org/wiki/%E6%95%B0%E7%8B%AC)で御覧下さい。
問題を作るには、まず解けなくてはいけないと思い、解答するプログラムをつくりました。
それで、問題作成にとりかかっているのですが、上手くできません。
考えている方法は、
1、行・列・3*3ボックスで重複しないように、ランダムに81マスを全部埋める。
2、そこから、適当なマスを空(0)にする。
3、その問題が、解答プログラムで解けたら、問題作成終了
という感じで作ろうと思っています。
そして今、1番で悩んでいます。
バックトラックという方法を見つけたのですが、それをどのように実装したらいいのかわかりません。
どなたか教えていただけないでしょうか。
初心者なので、易しく教えてください!
お願いします!
C言語で数独の問題をつくる
Re:C言語で数独の問題をつくる
お返事ありがとうございます!
問題を解くとこまではできてます。
問題作成の部分は、下の関数で作っています。
見にくくてもうしわけないのですが...
説明は下に書いておきます。
Cell_[行][列]は、各マスの構造体で、detとBox_numというメンバをもっています。
detには最初、0が入っていて、ランダムに決めた数字を入れていきます。
Box_numにはそのマスのボックス番号が入っています。
ここで言うボックス番号とは、3*3のボックスを左上から順に、
0 1 2
3 4 5
6 7 8
という風にしました。
あと、poss_Row[行][数字]とposs_Line[列][数字]とposs_Box[ボックス番号][数字]は各行・列・ボックス
に[数字]が入っているかどうかを入れていきます。
最初は全て0が入っていて、その数字が行・列・ボックスに入ったら、1に変えます。
これで、32マスが埋まったら止まるのですが、解が存在しない問題が出来てしまいます。
そこで、81マス全てを埋めてから、数マスずつ空にしていく方法に変えようと思ったのですが、
どうやったら、81マス全てを埋められるのか、わからなくて質問しました。
わかりにくい説明でもうしわけありません。
問題を解くとこまではできてます。
問題作成の部分は、下の関数で作っています。
見にくくてもうしわけないのですが...
説明は下に書いておきます。
void Rand_prob (void) { int rand_num = 0; int det_count = 0; for(;;){ i = rand() %9; j = rand() %9; if(Cell_[j].det == 0){ rand_num = rand() %9 + 1; if(poss_Row[rand_num-1] == 0 && poss_Line[j][rand_num-1] == 0 && poss_Box[Cell_[j].Box_num][rand_num-1] == 0){ Cell_[j].det = rand_num; det_count++; poss_Row[rand_num-1] = 1; poss_Line[j][rand_num-1] = 1; poss_Box[Cell_[j].Box_num][rand_num-1] = 1; } } if(det_count == 32) break; } }
Cell_[行][列]は、各マスの構造体で、detとBox_numというメンバをもっています。
detには最初、0が入っていて、ランダムに決めた数字を入れていきます。
Box_numにはそのマスのボックス番号が入っています。
ここで言うボックス番号とは、3*3のボックスを左上から順に、
0 1 2
3 4 5
6 7 8
という風にしました。
あと、poss_Row[行][数字]とposs_Line[列][数字]とposs_Box[ボックス番号][数字]は各行・列・ボックス
に[数字]が入っているかどうかを入れていきます。
最初は全て0が入っていて、その数字が行・列・ボックスに入ったら、1に変えます。
これで、32マスが埋まったら止まるのですが、解が存在しない問題が出来てしまいます。
そこで、81マス全てを埋めてから、数マスずつ空にしていく方法に変えようと思ったのですが、
どうやったら、81マス全てを埋められるのか、わからなくて質問しました。
わかりにくい説明でもうしわけありません。
Re:C言語で数独の問題をつくる
問題作成プログラムを検索で見つけたのですが、コードを理解できません。
実行すると、問題(全て埋まった状態)が無限に出続けます。
これを1回で止めるにはどうしたら良いですか?
できればコードの意味も説明していただけると嬉しいです。
宜しくお願いします。
<pre>
#include <stdio.h>
int a[81],c[10],j,k;
o()
{
for(j=80;~j;j--)for(k=80;k>j;k--)if((j/9==k/9||j%9==k%9||(j/27==k/27&&j%9/3==k%9/3))&&a[j]==a[k]&&a[j])return 0;return 1;
}
s(n)
{
int i=80;if(a[n])s(n+1);else if(n>80){for(;~i;i--)printf("%d%c",a,i%9?32:10);puts("\n");}else{for(i=1;i<=9;i++)(a[n]=i,o()?s(n+1):0,a[n]=0);}
}
int main(i)
{
i=80;
o();
s(0);
}
</pre>
実行すると、問題(全て埋まった状態)が無限に出続けます。
これを1回で止めるにはどうしたら良いですか?
できればコードの意味も説明していただけると嬉しいです。
宜しくお願いします。
<pre>
#include <stdio.h>
int a[81],c[10],j,k;
o()
{
for(j=80;~j;j--)for(k=80;k>j;k--)if((j/9==k/9||j%9==k%9||(j/27==k/27&&j%9/3==k%9/3))&&a[j]==a[k]&&a[j])return 0;return 1;
}
s(n)
{
int i=80;if(a[n])s(n+1);else if(n>80){for(;~i;i--)printf("%d%c",a,i%9?32:10);puts("\n");}else{for(i=1;i<=9;i++)(a[n]=i,o()?s(n+1):0,a[n]=0);}
}
int main(i)
{
i=80;
o();
s(0);
}
</pre>