ページ 11

(ゲームプログラミング)配列への答えの格納で困っています

Posted: 2012年6月04日(月) 11:49
by knotn
バックトラック法により数独の問題から答えを導き、それを配列に格納するプログラムです。
(大まかな手順)
OutQues関数で問題を2次元配列から1次元配列に直した後、AnalysisQues関数に送っています。さらに、バックトラックにより答えを求めた後、
1次元配列から2次元配列に格納し直しています。
(問題)
バックトラックで答えを求めた後、1行目までは2次元配列の方に格納されるのですが2行目の途中から答えを格納できていません。その理由が
分からないので教えて下さい。お願いします。

コード:

#include "DxLib.h"
#include "spgame.h"

void OutQues()
{
	/*int *map_handle;*/
	int no [9][9]={//mapdataの配列は0~80までの要素
		{0,5,6,0,0,2,0,9,7},
		{0,0,0,0,0,0,1,6,3},
		{0,0,1,0,8,0,0,0,0},
		{2,0,5,8,1,6,0,0,9},
		{0,0,0,5,7,4,2,8,0},
		{6,7,0,0,2,3,4,0,0},
		{0,2,0,3,9,0,0,4,8},
		{1,9,3,4,6,0,7,5,0},
		{8,0,4,0,5,7,9,3,1}
	};
	int Answer[81];
	int count = 0;

	int Mizu = GetColor( 145 , 197 , 255 ) ; 
	int brack=GetColor(0,0,0);

	
  //マップを表示
    int i,j;
	int x,y;
    zh.x1 = 23; 
	zh.y1 = 23;
	zh.x2 = 67;
	zh.y2 = 67;
		for(j = 0 ; j < 9 ; j++)
		{
			for(i = 0; i < 9 ; i++){
				zh.cel[i][j]=no[i][j];
			}
		}

		for( y=0 ; y<9 ; y++)
		{
			for( x=0 ; x<9 ; x++)
			{
				if(zh.cel[x][y]==1)
				{
					DrawBox( 23+y*50 , 23+x*50 , 70+y*50 , 70+x*50 , brack , TRUE );
					DrawFormatString( 45+y*50 , 45+x*50, Mizu, "%d", zh.cel[x][y] );
				}
				else if(zh.cel[x][y]==2)
				{
					DrawBox(23+y*50 , 23+x*50 , 70+y*50 , 70+x*50 , brack , TRUE );
					DrawFormatString( 45+y*50 , 45+x*50, Mizu, "%d", zh.cel[x][y] );
				}
				else if(zh.cel[x][y]==3)
				{
					DrawBox( 23+y*50 , 23+x*50 , 70+y*50 , 70+x*50 , brack , TRUE );
					DrawFormatString( 45+y*50 , 45+x*50, Mizu, "%d", zh.cel[x][y] );
				}
				else if(zh.cel[x][y]==4)
				{
					DrawBox( 23+y*50 , 23+x*50 , 70+y*50 , 70+x*50 , brack , TRUE );
					DrawFormatString( 45+y*50 , 45+x*50, Mizu, "%d", zh.cel[x][y] );
				}
				else if(zh.cel[x][y]==5)
				{
					DrawBox( 23+y*50 , 23+x*50 , 70+y*50 , 70+x*50 , brack , TRUE );
					DrawFormatString( 45+y*50 , 45+x*50, Mizu, "%d", zh.cel[x][y] );
				}
				else if(zh.cel[x][y]==6)
				{
					DrawBox( 23+y*50 , 23+x*50 , 70+y*50 , 70+x*50 , brack , TRUE );
					DrawFormatString( 45+y*50 , 45+x*50, Mizu, "%d", zh.cel[x][y] );
				}
				else if(zh.cel[x][y]==7)
				{
					DrawBox( 23+y*50 , 23+x*50 , 70+y*50 , 70+x*50 , brack , TRUE );
					DrawFormatString( 45+y*50 , 45+x*50, Mizu, "%d", zh.cel[x][y] );
				}
				else if(zh.cel[x][y]==8)
				{
					DrawBox( 23+y*50 , 23+x*50 , 70+y*50 , 70+x*50 , brack , TRUE );
					DrawFormatString( 45+y*50 , 45+x*50, Mizu, "%d", zh.cel[x][y] );
				}
				else if(zh.cel[x][y]==9)
				{
					DrawBox( 23+y*50 , 23+x*50 , 70+y*50 , 70+x*50 , brack , TRUE );
					DrawFormatString( 45+y*50 , 45+x*50, Mizu, "%d", zh.cel[x][y] );
				}
			}
			ScreenFlip();
		}

		for(i=0;i<9;i++)
		{
			for(j=0;j<9;j++)
			{
			 Answer[count] = no[i][j]; 
			 count++;                                //2次元から1次元に変えている。
			}
		}
		AnalysisQues(Answer, 0); //Answer[coount]を次の関数に送っている。デバッグしましたがおそらく遅れていると思います。
}
[code=c]
#include "DxLib.h"
#include "spgame.h"
#include<stdio.h>

void AnalysisQues(int Answer[], int pos)
{
	int x, newPos;
	int m,n;
	int Niji_Answer[9][9];
	//Solution is found.
	if (pos==N*N) {
		return;
	}

	//Find a blank.
	for (newPos=pos; newPos<N*N; ++newPos) {
		if (Answer[newPos]==0) break;
	}
	//Check recursively.
	for (x=1; x<=N; ++x) {
		if (canBePlaced(Answer, newPos, x)) {
			Answer[newPos]=x;
			AnalysisQues(Answer, newPos+1);
			Answer[newPos]=0;
			//backtracking
		}
	}

	int count = 0;
	for(m=0;m<9;m++)
	{
		for(n=0;n<9;n++)
		{
			Niji_Answer[m][n] = Answer[count];  //上記の所作で求めた数独の答えを1次元配列から2次元配列に
			                                                       //格納し直している。  ※1行目と2行目の途中までは正しい答えが格納
			                                                       //されているのですが、そこから先に格納されません。
			count++;
		}
	}
}


int canBePlaced(int Answer[], int pos, int x){ 

	int row=pos/N;
	int col=pos%N; 
	int i, j, topLeft;

	for (i=0; i<N; ++i) {  
	if (Answer[row*N+i]==x) return 0;
	if (Answer[col+i*N]==x) return 0;
	}

	topLeft=N*(row/B)*B+(col/B)*B;
	
	for (i=0; i<B; ++i) {
		for (j=0; j<B; ++j) {
			if (Answer[topLeft+i*N+j]==x) return 0;
		}
	}
	return 1;
}
[/code]


あと、付け足しでこのプログラムをこうした方がもっと良くなるといった改善点があれば良かったら教えてください。

Re: (ゲームプログラミング)配列への答えの格納で困っています

Posted: 2012年6月04日(月) 17:49
by ookami
こんにちは。ookamiです。
数独の答えを格納しているのは、AnalysisQues関数内のNiji_Answerってことであってますか?
一方、答えを表示しようとしているのはOutQues関数だと思います。
ところが、OutQues関数内では、「解く前の状態を表示してから」「答えを計算しようとしている」、ように見えます。

Re: (ゲームプログラミング)配列への答えの格納で困っています

Posted: 2012年6月04日(月) 23:32
by knotn
ookamiさんへ
わかりにくくてすみません。
おっしゃる通りOutQues関数では解く前の問題を表示してから、
AnalysisQues関数でその問題を解かしています。
ですが、AnalysisQues関数での計算がうまくいっていないためか、
問題の1行目と2行目の途中から答えを計算してくれません。(デバッグ後、配列を見ると0のまま)
どこが間違っているように思われますか。

Re: (ゲームプログラミング)配列への答えの格納で困っています

Posted: 2012年6月05日(火) 08:59
by ookami
おっとw そうでしたか^^;
とりあえず「答えの表示」は置いておいていいわけですね。

1.
「Niji_Answer」に格納されない、ということですが、「Answer」には格納されているのでしょうか?

2.
あと、気になるのは、「AnalysisQues」関数を
AnalysisQues(Answer, newPos+1);で再帰しているようですが、
その後のfor2重ループの中で、
Niji_Answer[m][n] = Answer[count]; されているので、
再帰した回数分、
「//上記の所作で求めた数独の答えを1次元配列から2次元配列に格納し直している」
ことになりますが、
意図通りの動きでしょうか?