dポイントプレゼントキャンペーン実施中!

数独の解答を一発で出すプログラムを考えています。
自分が考えたプログラムは下記の通りです。

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プログラムを下のプログラムのようにするにはどうしたら良いでしょうか。

A 回答 (2件)

簡単な方法は…。



Cのもともとの、問題作成関数あるよね?
これをcreate()と呼ぶことにする。


void create(){
for(){


if(){goto start;}
}
}

となってるよね。

これを、
GOTO文を消す方向で書き直すと、

void A(){
while(true){
if(create()){break;}//完成したら終了
}
}

boolean create(){
for(){


if(){return false;}//問題が未完成ならfalse
}
return true;//完成ならtrue
}

ローカル変数は適宜、"グローバルな"位置に移してね。
これでうまくいくんじゃないかな?

上記のように「関数の2重化」を用いないで、
1つの関数だけで、制御構造を工夫してなんとかするやりかたもあるけど、
ややこしいかも。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
やってみたいと思います。

お礼日時:2011/02/09 11:22

http://oshiete.goo.ne.jp/qa/6505044.html
を参考にしてどうなったの?
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
前の質問で回答して下さった方々の方法もやってみましたが、上手くいきませんでした。
因みに、前の質問でchie65535さんのプログラムをJavaに変えようとしましたが、無限ループに入ってしまい、上手くいきませんでした。

質問したC言語のプログラムを自分なりにJavaプログラム直したら、下記のようになりました。

import java.util.Random;

public class NumberPlaceA {
public static void main(String[] args) {
int i, j, k, l, check = 0, num = 0, count = 0, tmp;
int a[][] = new int [9][9];
Random rnd = new Random();
int ran;
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;
start:
while(num<9){
ran = rnd.nextInt(9);
i = ran;
j = ran;
check=0;
for(k=0;k<9;k++)
if(a[i][k]==tmp)check=1;
for(k=0;k<9;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]==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) break start;
count++;
}
}
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");
}
}
}

これを実行すると、
3 0 0 0 0 0 0 0 0
0 9 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 7 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 2 0
0 0 0 0 0 0 0 0 0

となります。

お礼日時:2011/02/08 09:43

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!