• ベストアンサー

数独をとくプログラム

C初心者です。大学生です。 タイトルの通り、Cで数独を解くプログラムを考えています。 数独については http://www.nikoli.co.jp/puzzles/1/ をご参照ください。 で、数独にも難易度があり、初めからある程度数字が埋まっている(簡単な) 問題を解くプログラムは作ることが出来ました。 単純に、各マスの構造体Cellに対してsign[1],sign[2],,,,,sign[9]を定義し、 それが1なら可能性あり、0なら可能性なし、として (例えばsign2]==1,sign[5]==0ならそのマスは2になる可能性はあるが5になることはない) 丹念に各マスに対してそのマスが属するブロック、列、行を調べて最後まで1であるflagを探すようにしたのです。 しかし初めから埋まっている数字が少ないと(難しいと)そもそも回答が1通りでない、 などの理由から上記のアルゴリズムでは解くことが出来ません。 あきらかにどこかをあてずっぽに仮定する作業(バックトラック?) が必要になりそうです。 ・・・が、それをどうやって実現したらいいかで行き詰っています。 どうか知恵を貸してください。よろしくお願いいたします。。。

  • R-gray
  • お礼率41% (1005/2413)

質問者が選んだベストアンサー

  • ベストアンサー
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.8

#7の問題は、私のプログラム(制約によるマス埋めのもの)でも解けませんでした。 結果: +---+---+---+ |200|670|000| |906|000|201| |400|000|800| +---+---+---+ |500|009|380| |830|000|150| |102|835|007| +---+---+---+ |301|000|004| |708|000|600| |600|053|008| +---+---+---+ #1でも言ってますけど結局上級問題は単なる制約によって埋めていくだけでは解けない問題があると思います(私のプログラムの抜けがあるのかもしれませんが)。 ちなみに 解け残りの左上の正方ブロック +---+ |200| |906| |400| +---+ の部分で +---+ |2X0| |906| |400| +---+ +---+ |200| |906| |4X0| +---+ のXの部分で1が見合い(どちらかに1が入る)になっています。 上の方に1を入れたら手詰まりで 下の方に1を入れたら解けました。 +---+---+---+ |283|671|945| |976|548|231| |415|392|876| +---+---+---+ |567|419|382| |834|267|159| |192|835|467| +---+---+---+ |321|786|594| |758|924|613| |649|153|728| +---+---+---+ なので、やはり、そういう仮にどこそこへXを入れたらどうなるという仮の実行をしてみれば解けるということになります。 普通、手詰まりになってからそのような探索を始めれば、 数独自体制約が厳しいパズルなので、全探索する前に解が求まると思います。(なので、それほど深い再帰にはならないと思われます) 解が複数あることを調べる場合には、全探索しないといけないと思われますが、その場合は、見つかった解を見つからなかったとして(バックトラックして)探索を続けるということになろうかと思います。 メモリが豊富に使える昨今では多分大丈夫じゃないでしょうか。 ただ、数独のパズルとしては、解が2つ以上あるというのは、ミスだと思うので、全探索する必要はないと思っています。

その他の回答 (8)

  • swimeye
  • ベストアンサー率0% (0/3)
回答No.9

#7の問題は、手作業ですが理詰めだけでとけました。 また、#4さん回答にあるサイトにJava Appletがあり、 そちらでも解けるようです。 このサイトは仮定(背理法)を使う機能もあるようですが、 この機能なしでも解けました。 素人作成の問題はともかく、プロの作った問題は理詰めで解けることが 特徴のひとつです。 手元にニコリ社の数独の問題集(難問ばかり)がありますが、 理詰めで解けることが明記されています。 中には上記のサイトでも理詰めだけでは解けないものがありますが、 何とか自力では理詰めで解けたので、"仮定を入れないと解けない" という発想は捨てたほうがよいでしょう。 課題の趣旨がコーディング技術だけならいいですが、 アルゴリズム考案を含むなら、減点対象にもなりかねませんので。 考え方がまったくわからなくて、他人に聞くことが反則に ならないなら、#4さんのサイトを見るのが早いですが、 その内容の説明なり、もう少し軽いヒントなり、 多少のアドバイスはできます。 ご健闘ください

参考URL:
http://puzzle.lavot.com/java/numberplace/index.html
R-gray
質問者

お礼

わぁ。。。。。 できました。quiz3もきちんと解いてくれました。 本当にうれしいです。参考URLも参考にしました。 ”ある行で同じ2つの候補を持つマスが2つあるときその他のマスから その2つの候補を消す”というのがかなり効きました。 BLUEPIXYさんのご自身のプログラムでの出力がヒントになって いろんなことに気づいて色々改善できました。 本当に感謝の気持ちでいっぱいです。 正直皆さんに100ポイントくらい上げたいのですが特にお世話になった 方々にポイント配分させていただきます。 でも本当に皆さん全員に感謝しています。 ありがとうございました!!! ちなみにquiz3の回答は以下のように成りました。 +---+---+---+ |283|671|945| |976|548|231| |415|392|876| +---+---+---+ |567|419|382| |834|267|159| |192|835|467| +---+---+---+ |321|786|594| |758|924|613| |649|153|728| +---+---+---+

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.7

#6>現段階で私の作ったのが理詰め(だけ)でやってくれるやつです。 昔、理詰め(だけ)でやってくれるやつを作ったことがあるのですが、 #6の問題は解けましたよ。 692381547 435627189 187549236 918274653 574936821 263158794 746892315 321465978 859713462

R-gray
質問者

お礼

昨晩から改良を続けていました。でANO.6の問題が解けました! BLUEPIXYさんのと全く同じ回答になったのでひと安心です。 …ダメだったところがわかり、それでもう完璧かと思ったのですが (課題の問題は3問あって、1,2は解けた) 最後のquiz3を実行したら解けませんでした。。。 たびたび申し訳ないのですがBLUEPIXY様の理詰めで説くプログラムは下の問題は解けますでしょうか? もう正直これ以上何をしていいのかわかりません。。。 正直皆様にソースを見て指摘してもらいたいのですが課題提出用ですしこのページも普通に検索に引っかかるので 躊躇われるところです。なにかいい手があれば良いのですが。 +---+---+---+ |200|670|000| |006|000|201| |400|000|800| +---+---+---+ |500|009|300| |030|000|050| |002|800|007| +---+---+---+ |001|000|004| |708|000|600| |000|053|008| +---+---+---+ 本当に申し訳ないのですができればお願いいたします。。。

R-gray
質問者

補足

お礼補足です。一番大事なことが抜けていました。 回答ありがとうございました。長々と付き合っていただけて本当に助かっています。。。

  • Qwerty-36
  • ベストアンサー率25% (58/226)
回答No.6

数独をとくプログラム、Win32版、作りました。 そこそこ動いています。 9×9をブルートフォースではなく、自分が"1"だと確定したら、「関連するセル」に『僕は"1"になったよ』って、メッセージを飛ばせば良いんです。 で、そのメッセージを受けたセルは、「あ、こいつから"1"だってメッセージ受けたから自分のセルの候補リストから"1"を消そう」、で次に「候補リストを見たら5しか残ってないぞ」、「じゃ自分は"5"だと宣言してしまえ」で上に戻ります。 判るかなぁ。こんな物で(^^;)。 確定したセルがメッセージを出し、受け手がメッセージで自分のリストを見直し、その結果、確定したセルが増えていく。 面白いですよ。問題を入力していると、パラパラとセルの内容が書き込まれていきます。 # メッセージを飛ばすのに、WM_Userを使ったので、上手く動かないときがありますが。

R-gray
質問者

お礼

これだとやはり限界がないですか? 自分的にはやはり総当りは不可欠だと思っているのですが。 現段階で私の作ったのが理詰め(だけ)でやってくれるやつです。 例えば 600 000 540 030 027 000 000 009 000 000 000 053 004 000 800 260 000 000 000 800 000 000 460 070 059 000 002 という問題ですと('0'は空白を示します) 私のお馬鹿プログラムは 600 000 540 430 027 000 000 049 000 000 004 053 004 000 800 260 000 004 046 890 000 000 460 070 059 000 402 までしか突き止めてくれません。 ちなみにこのお馬鹿プログラムでも http://www.nikoli.co.jp/puzzles/1/ の問題はきちんと完答してくれます。

R-gray
質問者

補足

*********************************** *********************************** すみません、ここまでやっておいて何なのですが 先ほどANo.6に対するお礼にかいたプログラムの出力結果と 同じものを新に問題として作って(datファイルにして)再度同じプログラムに 解かせたところなんと一歩前進していました。 そこで何かおかしいところがあると思いテストをしていくと 必須であると思っていた関数の一つを/*.....*/でくくっても 出力に変わりなかったのです。つまりそれがおかしいということです。 もしかしたら+αでうまくいけるかもしれません。 とりあえず今までの自分にとんちんかんなミスがあったことをお詫びいたします。 申し訳ありませんでした。 ただ今回でバックトラックなどについて少し詳しくなったので無駄ではないと思っています。 *****************************************

  • chirubou
  • ベストアンサー率37% (189/502)
回答No.5

多分答えには全くなっていないとは思うのですが。 私ならバックトラックを自動で行ってくれる Prolog を使います。

R-gray
質問者

お礼

なるほど。。。wikiで調べてみました。 確かにProlog(使ったことないです)だと簡単に実現できるそうですね。 もしPrologとやらに触れる機会あれば試して見ます。 ご回答ありがとうございました。

R-gray
質問者

補足

ちなみにこの数独のプログラムは大学のCの課題ですので やはりCでやらなければいけません。。。

  • Trick--o--
  • ベストアンサー率20% (413/2034)
回答No.4

注意:ナンバープレースの解き方に触れています。読みたくない方はご注意ください。 http://puzzle.lavot.com/java/numberplace/algorithm.html 仮定したものを覚えておけばいいじゃない。 理詰めで解けなくなった時点で、問題が成立していないと思うが。

R-gray
質問者

お礼

これはもう少し突き止めてみることにします。 ありがとうございました!

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.3

#1>全部で3*3*2=18通りの組み合わせがありますが、それらを全て試させるには 例えば、 Aマスで2通り、Bマスで3通りある場合、 Aの状態で(仮に)1つ決定して問題を解かせると、 ・問題が解けた ・問題が解けずに行き詰まった という状態になります。 問題を解く手順として、問題が解けずに行き詰まった場合の手順として、決定していないマスの手を1つ選んで仮に進めるという手法を組み込み済みなので、Aが埋まった状態でBのマスの状態を調べる状態になります。 そのように再帰的に手順が呼び出されて(メモリがオーバーフローしないで正解があるなら)いつか結果が求まります。 その場合、 最初のAマスの1つの探索が終わったとき次の(残りの)1つの手を調べるようになっていれば、 結果的に、全ての組み合わせを調べることになります。(樹形図を描いたような感じで、プログラムが再帰的に木を深さ優先でたどる)

R-gray
質問者

お礼

再帰を使えば確かにうまくできそうです。。。が正直いまいち再帰がわかっていない私。。。 でも特に不確定マスの個数が状況による、となると再帰を頼らずにはいられなさそうです。 もしくはwhile(1)で永遠ループを作って、あるifの元でbreakさせるか。。。 http://www.pro.or.jp/~fuji/puzzlestudy/sudoku.html のサイトのbakadoku.cというファイルだと再帰を使ってシンプルに 実現しているようなのですが正直ソースを見てもよく仕組みがわかっていません。。。 ご解答ありがとうございました。

  • dra2jp
  • ベストアンサー率25% (18/72)
回答No.2

数独ですかぁ、ひゃ~難しそうですねぇ。 解き方がわからないのでプログラムかけませんけど >マスAの候補が1,3,5、マスBの候補が3,4,7、マスCの候補が8,9、出会った場合、全部で3*3*2=18・・・ の部分だけお答えしましょう。 3*3*2の18通りの組み合わせの計算は3つのfor文で組み合わせ可能です。 (1,3,5) * (8,9) * (3,4,7) の18通りの組み合わせ方(i*j*s)をみてみましょう。 (1,3,5)にあたる部分がi (8,9)にあたる部分がj (3,4,7)にあたる部分がs です。 for(i=1;i<=5;i+=2){ ___for(j=8;j<=9;j++){ ______for(s=3;s<=5;s++){ _________if(s==5) ____________s=7 _________(処理) ______} ___} } i,j,sにマスA,B,Cの条件を適応させれて(処理)で処理させれば組み合わせのプログラムは出来ます。 数独面白そうですね。 よければプログラムも見せてもらいたいです^^

R-gray
質問者

お礼

御礼遅れました。 しかし回答の方法ですと、例の場合は前半の(1,3,5),(8,9)が等差数列になっているので forループで簡潔に実現できますが、これが実際は(1,4,9)だか(1,2,9)だか、そもそも 仮定するマスの数すら未定なのですから(今回の例がたまたま3つだった)forループでやるのは無理ではないでしょうか? もし私の思い違いであれば教えてください。お願いいたします。

R-gray
質問者

補足

すみません、お礼の追記です。 プログラムソースは(私のアルゴリズムが泥臭すぎるというのも手伝って) 400行を越えてしまっているのでこの場での公開は辞退させてください。 すみません。それとご回答ありがとうございました。

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.1

>回答が1通りでない、 場合は、問題に問題ありで、問題として不適当だと思いますが、 単純に、 >丹念に各マスに対してそのマスが属するブロック、列、行を調べて最後まで1であるflagを探すようにしたのです。 だと上級問題が解けないですね。 言われるようにトラックバックを実装する必要があると思います。 数独を解くルーチンの独立性を高めて、 "1であるflagを探す手順"で行き詰まった段階で 今考えている9×9のフィールドのコピーを作り、可能性リストの小さいものから 仮にその1つを入れたものを作成してその問題を解かせてみて完成するようならOKみたいにすればどうでしょう

R-gray
質問者

お礼

ご解答ありがとうございます! >>可能性リストの小さいものから >>仮にその1つを入れたものを作成してその問題を解かせてみて ここの部分でとまどっています。確かに候補が3つ以下、2つ以下のマスを 見つけることは出来ます。ですが例えばマスA,B,Cを仮定するとして、マスAの候補が1,3,5、マスBの候補が3,4,7、マスCの候補が8,9、出会った場合、 全部で3*3*2=18通りの組み合わせがありますが、それらを全て試させるにはどのような アルゴリズムを組めばよいのでしょうか・・・。

関連するQ&A

  • 数独かを判断するプログラム

    私が作ろうとしているプログラムは数独を解くものではなく、予めテキストファイルに書かれている横9つ縦9つ、計81個の数字の表が、数独として成り立っているかを判断するものです。 数独についてはこちらで http://ja.wikipedia.org/wiki/数独 or http://sudoku.ara3.net/rule.htm 配列をa[9][9]と用意し、テキストファイルから数字を左上から順に配列に確保していき、その表が数独かどうか判断する段階で躓いています。3×3のマスの中に1~9までの数字が1個ずつあり、かつそのマスが計9つあれば数独なので、まず最初の3×3のマスの中の数字を1~9まで確認し、それを残り8つのマスにも同様に繰り返すだけで良いと思うのですが、その方法がわからず困っています。どなたかお解かりになる方、よろしくお願いします。 例として、テキストファイルの数字の表は以下の様になっています。 1 2 3 4 5 6 7 8 9 4 5 6 7 8 9 1 2 3 7 8 9 1 2 3 4 5 6 2 3 4 5 6 7 8 9 1 5 6 7 8 9 1 2 3 4 8 9 1 2 3 4 5 6 7 3 4 5 6 7 8 9 1 2 6 7 8 9 1 2 3 4 5 9 1 2 3 4 5 6 7 8 ちなみにこの表は数独として成り立っています。

  • javaで数独を解くプログラムについて

    java初心者です。 学校で数独を解けという問題が出て、問題の意味もまったくわからないのでヒントください。 問題 数独を解くプログラムを作成せよ。ただし、すでに埋まっているマスを入力する時にはi,j,n(改行)でひとつの数字を入力できるものとし、終了条件は、0,0,0を入力するとする。 問題用紙には1問だけ数独が載ってあるのですが、 初歩的な質問で申し訳ありませんが まずこのプログラムは、その1問だけ載っているマスが少し埋まっているプログラムを打ち込んでから解くプログラムを考えるのでしょうか? 普通、数独を解くプログラムとは、空いているマスにキーボード入力して、解くのでしょうか?それとも自動に動いて解くのでしょうか? はじめにプログラムをコンパイルしたときにどう言葉が出るようにすればようのでしょうか? 終了条件0,0,0とは、000を入力したら終わる?ということでしょうか? マスを作って、クリックすると数字が…というようなjavaは習ってなくコマンドプロントでコンパイルだけなので、数字を打って入力、エンターというだけで解くのだと思うのですが、まったくわからないです。 根本的にわからなくてすいません。 ぜひご回答よろしくおねがいします。

  • 数独(ナンプレ)の解き方(アルゴリズム)

    プログラミングの宿題で、Javaを使って数独を解くプログラムを作っています。雑誌などにある数独の問題を解くことはできたのですが、今回はその問題もプログラムで作ってそれを解かせようというお題になってしまいました。今のところ下のような感じになっています。 1. 乱数を使って0-80までのマス番号に1-9の数字を数個適当に入れていきます。(0が左上の角で、80が右下の角です。) 乱数でマスに数字を入れますから、同じマスに数字が入ることがありますが、それはそれでそのマスを上書きしています。さらにこの段階で、数字が同じ列または3×3マスで重なることがないようにしています。 2. それを元に各マスに入る可能性のある数字をリストアップ 3. リストアップした中で、最後に必ず1つだけ数字が残るのでそれをそのマスに入れます。 とここまではできました。しかし、乱数で適当に問題をつくったにしか過ぎないから、当然ダブってしまうところや、数字が入らないマスがあります。ですから、そういったダブるところや数字の入らないマスのために補正をしたいと思うのですが、まったくアイディアが浮かびません。どのようにしたら補正をして問題を回答できますか? アルゴリズムが少々長くてもかまいません。また、Javaのコードでの回答でなくてもかまいません。とにかく、如何の様に補正するのかを知りたいです。 下にあるのが、上の1.で作った問題です。 # 0は数字が入っていないマスを示します。 060 | 000 | 080 030 | 080 | 017 000 | 100 | 000 --------------- 800 | 000 | 903 000 | 803 | 060 000 | 096 | 500 --------------- 908 | 407 | 000 205 | 000 | 400 700 | 001 | 000

  • 数独の3国同盟のアルゴリズム教えて下さい

    はじめまして! C言語を勉強して3ヶ月になります、現在、勉強のつもりで数独の解法プログラムを作っています が、解法プログラムを基本から順に実装しようと基本から2国同盟まではわかったのですが3国 同盟以上(まずは自明のNaked Tripleからお願いします<(_ _)>)のアルゴリズムがどうしても 解らずプログラムが書けません。マスの絞り込み方です。例えば横ラインのマスで候補数が2、 3個のマスに絞って・・・次ですが3個のマスには3種類しか入らない。・が解りません!目 で見ればわかりますがそれをプログラムする方法)NAKED(見える)Tripleだけで良いので考え方 を教えて下さい。2日間詰まってます(>< ) どうぞ宜しくお願いします<(_ _)> (例) R3横一行だけを考えたときにR3C1(6,8)、R3C2(1,6)、R3C3(2,3,4)、R3 C4(1,8)、R3C5(1,2,4,5,6)・・・で()内は候補数です。これはC1、C2、C4で (1,6,8)の3国同盟ができています。R3C5の(1,6)は削除され候補数(2,4, 5)となる。悩んでいるのはC1、C2、C4を同盟決定のアルゴリズムです。 「異なる3つのマスを選んだときに、それら3マスに入れられる候補の種類が3種類であること」を プログラム上でどう表現したら良いかずっと詰まってます(>< ) どう考えたらこの3つのマスを決定(同盟関係)できるのでしょうか?宜しくお願い致します<(_ _)>

  • エクセルVBAで数独

     エクセルのVBAを使って、ナンバープレイス(数独?)の問題を創りたいのですが、どうすれば良いでしょう?  一応、以下の条件で自分で組んでみました。  ○各マス目で、「縦9マス」「横9マス」「3×3マス」中に有る数字を【1~9】内から消去し、残った数字内からランダムで挿入する数字を決定する。  ○処理中に、どうしても決定できないマス目が発生した場合は、決定済みのマス目をある程度チャラにし(処理を戻って)やり直す。  ○上記方法で、1~81までのマス目を埋めていく。  ○最後に、適当な数のマス目の数字を消去する。  一問作成するのに結構な時間がかかる上、時には完成しない(やり直し続ける)事態が発生します。  何か良い方法(アルゴリズム?)が有ったらご教示願います。  (…アルゴリズムを質問するのは、カテゴリー違いでしょうか?)

  • 4×4の数独の種類

    先日の大学入試問題で 出た問題です。 4×4のマスの中に 1~4の数字を 9×9の数独と同じルールで 埋めていきます。 そのとき何通り できるかを聞いています。 各塾で出した入試速報の中で いくつかの解答が間違った そうです。 一応答えは288通り なのですが、 どう解説したらよいかが よくわかりません。 どなたか教えて いただけませんか??

  • 迷路プログラム

    迷路プログラムの応用問題なのですが、上手くいかずに困っています。 問題 2次配列を用いて、縦横X,Yマスの迷路を作ります。 マスの数はX,Y共に最大100までの値であれば、任意の数が振れます。 迷路の一番左下がスタートS、一番右上がゴールGになります。 マスへは上下左右にしか移動出来ません。 迷路の中には任意で入力したXマスがあり、Xが入っているマスには移動出来ません。 S,G,Xが入っていないマスには、1~9までの数字を任意に入力します。 それぞれの数字は、そのマスに移動するためにかかるコストを表しています。 スタートからゴールまで、コストがもっとも小さくすむルートのコストを出力するプログラムを作りたいです。 また、Xマスでゴールが不可能な場合は-1を返します。 単純にゴールを目指すのと違い、コストがあると遠回りをしなければならない可能性があるので、そのアルゴリズムが思いつきませんでした。 例 11*7マスの迷路の場合 マスの数:11 7 迷路の値の入力: 7 9 3 3 6 3 X X 7 9 G 1 1 3 2 6 6 8 4 8 4 5 7 2 9 1 3 4 8 4 9 8 9 9 7 4 2 5 X 8 6 9 9 4 4 7 3 8 X 8 X 5 7 X 7 1 7 1 8 5 6 5 9 5 6 2 S 5 5 2 9 4 2 2 9 5 1 出力: 最小コストは59 迷路からゴールに進むだけのプログラムは作れたのですが、応用問題としてコストが入ると急に難しくなりました。 コストが絡むとどういうアルゴリズムで動けばいいのか分かりません。アドバイスをお願いします。

  • 数独の問題レベル決定のコツ

     9×9マス全てに数独のルール通り、重複無く「1~9」の数字を入れた後、適当数(一般的な問題で有る位)の空白を作り問題を完成させたいのです。    上記のやり方で、回答が1つだけになるようにしたい時、どのようにに空白を作れば難易度の調整が出来るのでしょうか?  空白場所を決定する『コツ』が有れば、お教えください。

  • 4×4数独の最少置数

    先日数学セミナーの問題で、4×4の数独には最低でも4つの数字が分かってないとだめ、ということを証明する問題が出ていました。 複雑で証明が理解できなかったのですが、      a(11)a(12) b(11)b(12)      a(21)a(22) b(21)b(22)      c(11)c(12) d(11)d(12)      c(21)c(22) d(21)d(22) と、各マスに未知数を振って、(各マスは1,2,3,4のみ) として、     a(11)+a(12)+a(21)+a(22)=1+2+3+4=10     b(11)+b(12)+b(21)+b(22)=10     c(11)+c(12)+c(21)+c(22)=10     d(11)+d(12)+d(21)+d(22)=10     a(11)+a(12)+b(11)+b(12)=10     a(21)a+(22)+b(21)+b(22)=10 c(11)+c(12)+d(11)+d(12)=10     c(21)+c(22)+d(21)+d(22)=10 a(11)+a(21)+c(11)+c(21)=10 a(12)+a(22)+c(12)+c(22)=10 b(11)+b(21)+d(11)+d(21)=10 b(12)+b(22)+d(12)+d(22)=10 「求める未知数が16個にたいして12個しか式がないから、少なくとも4個既知でなければならない」 は解答になっていないででょうか。

  • 数独のJavaプログラム

    数独の解答を一発で出すプログラムを考えています。 自分が考えたプログラムは下記の通りです。 import java.util.Random; public class NumberPlace { public static void main(String[] args) { int i, j, k, l, check=0, count=0, tmp; int a[][] = new int [9][9]; Random rnd = new Random(); int ran; for ( i=0; i<9; i++ ) for ( j=0; j<9; j++) a[i][j] = 0; count = 0; for ( i=0; i<9; i++ ) { for ( j=0; j<9; j++) { ran = rnd.nextInt(9); tmp = ran + 1; check = 0; for ( k=0; k<j; k++ ) if ( a[i][k] == tmp ) check = 1; for ( k=0; k<i; k++ ) if ( a[k][j] == tmp ) check = 1; for ( k=(i/3)*3; k<(i/3)*3+3; k++ ) for ( l=(j/3)*3; l<(j/3)*3+3; l++ ) if ( a[k][l] == tmp ) check = 1; if ( check == 0 ) a[i][j] = tmp; if ( check == 1 ) j--; if ( count > 50000 ) break; count++; } count = 0; } for ( i=0; i<9; i++) { for ( j=0; j<9; j++ ) { if ( a[i][j] < 10 ) { System.out.print(" "); } System.out.print(a[i][j]); } System.out.print("\n"); } } } これを実行すると、正しい数独の解が出来るまでに実行を20~30回。多い時は200回前後実行しないと出来ません。 実行結果(0は数独のルール上数字が入らない所) 9 3 6 5 4 1 7 8 2 1 7 4 2 9 6 5 3 0 5 2 8 7 3 0 0 0 0 2 1 5 3 7 8 4 6 9 8 6 3 4 1 9 2 7 5 4 9 7 6 5 2 1 0 0 7 5 1 8 6 4 9 2 3 3 8 2 9 0 0 0 0 0 6 4 9 1 2 5 8 0 0 これを一発で0がない状態にしたいのです。 因みにC言語だと下記のプログラムで一発で出るのですが。(前回質問したプログラム) int main(void) { int i,j,k,l,chk=0,num=0,tmp,count=0; int a[9][9];  srand((unsigned) time(NULL)); start: count=0; for(i = 0; i < 9; i++) for(j = 0; j < 9; j++) a[i][j]=0; for(tmp=1;tmp<10;tmp++){ num=0; while(num<9){ i = rand() % 9; j = rand() % 9; chk=0; for(k=0;k<9;k++) if(a[i][k]==tmp)chk=1; for(k=0;k<9;k++) if(a[k][j]==tmp)chk=1; for(k=(i/3)*3;k<(i/3)*3+3;k++){ for(l=(j/3)*3;l<(j/3)*3+3;l++){ if(a[k][l]==tmp)chk=1; } } if((chk==0)&&(a[i][j]==0)){ a[i][j]=tmp; num++; } if(count%100==99){ count++; for(i = 0; i < 9; i++) for(j = 0; j < 9; j++) if(a[i][j]==tmp)a[i][j]=0; num=0; } if(count>10000) goto start; count++; } } for(i = 0; i < 9; i++){ for(j = 0; j < 9; j++){ printf("%d ",a[i][j]); } printf("\n"); } return 0; } このプログラムを実行すると一発で解答が出ます。 上のJavaプログラムを下のプログラムのようにするにはどうしたら良いでしょうか。

    • ベストアンサー
    • Java

専門家に質問してみよう