2009年11月23日月曜日

ナンバープレース

新聞に毎週ナンバープレースと言うゲームが載っています。試しに解いてみたらプログラム化出来そうなので作ってみました。NumAを呼び出すときに引数を渡さなければ下記のnumbが問題とされます。引数ととして9x9の整数配列を渡す事も出来ます。いずれにしても回答が帰ります。途中結果の表示の箇所はコメントで無効化しています。これをJSPで読み出して使っています。まだ保管が出来ないので改造する予定ですが、、、ペーストして見たらインデントが消えていました。見づらいですけど編集も面倒なので。。

public class NumA {
static int[][] numb = {
{1,0,0,2,4,0,0,0,0},
{2,0,8,0,0,6,3,0,0},
{6,0,0,0,3,0,4,0,5},
{0,0,0,0,0,5,0,6,0},
{4,7,0,0,9,0,0,1,3},
{0,3,0,8,0,0,0,0,0},
{7,0,2,0,8,0,0,0,9},
{0,0,9,4,0,0,5,0,8},
{0,0,0,0,6,7,0,0,2}};

public static void main(String[] args){
int[][] numr = new int[9][9];
int i,j;
//問題の配列を表示
for (i=0; i<9; i++){
System.out.print("\n");
for (j=0; j<9; j++)
System.out.print(numb[i][j]+",");
}
NumA num = new NumA();
numr = num.NumA(numb);
//答えの配列を表示
for (i=0; i<9; i++){
System.out.print("\n");
for (j=0; j<9; j++)
System.out.print(numr[i][j]+",");
}
}

public int[][] NumA(int[][] numb){

int[][] numr = new int[9][9];//解析用
int[][] numc = new int[9][9];//変化の比較用
int[][][] result = new int[9][9][9];
int[] judg = new int[10];//判定用の配列 [9]が評価数値、0は要推定 [0~8]に1-9を入れて比較
int[] mark = new int[10];//判定用のマーク



int count = 0;//loopカウンター
int b,c;
int m,n;
int i,j,k;
//問題の配列をコピー
for (i=0; i<9; i++)
for (j=0; j<9; j++)
numc[i][j] = numr[i][j] = numb[i][j];
//問題の配列を表示
// for (i=0; i<9; i++){
// System.out.print("\n");
// for (j=0; j<9; j++)
// System.out.print(numr[i][j]+",");
// }
//評価
do{
//結果の配列をクリアー
for (i=0; i<9; i++)
for (j=0; j<9; j++)
for (k=0; k<9; k++)
result[i][j][k]=0;
for (m=0; m<9; m++){//行を指示
for (n=0; n<9; n++){//列を指示
judg[9]= numr[m][n];//判定用の配列judg[9]に評価数値を代入
if (judg[9] == 0){//評価数値が0なら判定作業
for (i=0; i<10; i++)//判定用のmark[0..9]に0-9を入れる
mark[i] = i;
//行判定
for (i=0; i<9; i++)//判定用の配列judg[0..8]にnumrの行を代入
judg[i]=numr[m][i];
for (i=0; i<9; i++)//数値が有ればmarkの該当位置に0を入力
if (judg[i] != 0)
mark[judg[i]]=0;

//列判定
for (i=0; i<9; i++)//判定用の配列judg[0..8]にnumrの列を代入
judg[i]=numr[i][n];
for (i=0; i<9; i++)//数値が有ればmarkの該当箇所に0を入力
if (judg[i] != 0)
mark[judg[i]]=0;

//ブロック判定
int bx = m/3;
int by = n/3;
for (i=0; i<9; i++)//判定用の配列judg[0..8]にnumrのブロックを代入
judg[i]=numr[bx*3+i/3][by*3+i%3];
for (i=0; i<9; i++)//数値が0が有ればばmarkの該当箇所に0を入力
if (judg[i] != 0)
mark[judg[i]]=0;

//推定される数値の数が1なら確定
j=0;
for (i=0; i<10; i++)//マークの空白=0以外を数える
if (mark[i] != 0){
result[m][n][j]=mark[i];
j++;
}
if (j == 1){//確定
numr[m][n]=result[m][n][0];
// System.out.print("\ndecidea:"+ m +":"+ n +"/"+numr[m][n]);
}
}//判定
}//n-loop
}//m-loop

//結果表示
// for (i=0; i<9; i++){
// System.out.print("\n");
// for (j=0; j<9; j++)
// System.out.print(numr[i][j]+",");
// System.out.print("..");
// for (j=0; j<9; j++)
// for (k=0; k<9; k++){
// if (result[i][j][k] != 0)
// System.out.print(result[i][j][k]+".");
// }
// }
//変化をチェック
b=c=0;
for (i=0; i<9; i++)
for (j=0; j<9; j++){
if (numc[i][j] == numr[i][j])
c++;
if (numr[i][j] == 0)
b++;
}
//今回の結果をコピー
for (i=0; i<9; i++)
for (j=0; j<9; j++)
numc[i][j] = numr[i][j];
// System.out.print("\nm,c,b="+m+","+c+","+b);
}while((count++ < 100) && (c != 81));
return numc;
}
}