数独について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
K-I

数独について

#1

投稿記事 by K-I » 18年前

今数独をとくプログラムを作成しています
#include <stdio.h>
int map1[9][9];
/* m:Mondai */
int p[9][9]={{0,0,6,0,0,0,0,0,1},
{0,7,0,0,6,0,0,5,0},
{8,0,0,1,0,3,2,0,0},
{0,0,5,0,4,0,8,0,0},
{0,4,0,7,0,2,0,9,0},
{0,0,8,0,1,0,7,0,0},
{0,0,1,2,0,5,0,0,3},
{0,6,0,0,7,0,0,8,0},
{2,0,0,0,0,0,4,0,0}};
void disp()
{ int i,j;
for (i=0;i<9;i++){
for (j=0;j<9;j++){
printf("%2d",p[j]);
}
printf("\n");
}
}
void main(void)
{
int i,j,k,l;


for (i=0;i<9;i++){
for (j=0;j<9;j++) map1[j]=0;
}

for(i=0;i<9;i++){
for(j=0;j<9;j++){
if (p[j] !=0) map1[j]=2;
if (p[j] ==1){
map1[j]=1;
}
for(k=0;k<9;k++){
if(map1[k][j] ==0) map1[k][j]=2;
if(map1[k] ==0) map1[k]=2;
}
for (i=0;i<7;i+3){
for (j=0;j<7;j+3){
for(k=i;k<k+3;k++){
for(l=j;l<l+3;l++){
}
}
}
}
}
disp();
}
}
私の考えは1の入る場所を特定する場合元の数の0以外を2 1を1 そして1の縦横を1にして3*3マスに0が一つ他が2のときその0に1が入るという考えで進めています 現在3*3のマスに0が一つ他が2の場所を作り3*3マスずつ調べていくところまでできたのですが どうやって0に1を入れていいのかというところで躓いています うまく説明できなくてすみません
利用規約を読んだんですが 質問のしかた間違っていたら申し訳ありません
どなたかアドバイスよろしくお願いします

K-I

Re:数独について

#2

投稿記事 by K-I » 18年前

書き忘れてすみませんOSはWindowsVistaHomeプレミアムです BorlandC++を使っています

Re:数独について

#3

投稿記事 by » 18年前

とりあえずソースを載せる時は<pre></pre>を使ってください。(もちろん半角で)

で、ソースがちょっと意味不明な個所がありました。
実行しながらやっていますか?

タブがおかしいのには目を瞑ってくださいorz

**以下改変したソース**

#include <stdio.h> 

int map1[9][9]; 
/* m:Mondai */ 
int p[9][9]={{0,0,6,0,0,0,0,0,1}, 
			{0,7,0,0,6,0,0,5,0}, 
			{8,0,0,1,0,3,2,0,0}, 
			{0,0,5,0,4,0,8,0,0}, 
			{0,4,0,7,0,2,0,9,0}, 
			{0,0,8,0,1,0,7,0,0}, 	
			{0,0,1,2,0,5,0,0,3}, 
			{0,6,0,0,7,0,0,8,0}, 
			{2,0,0,0,0,0,4,0,0}}; 

void disp(void) 
{
	 int i,j; 
	for (i=0;i<9;i++){ 
		for (j=0;j<9;j++){ 
			printf("%2d",p[j]); 
		} 
		printf("\n"); 
	} 
} 

void disp_2(void) 
{
	 int i,j; 
	for (i=0;i<9;i++){ 
		for (j=0;j<9;j++){ 
			printf("%2d",map1[j]); 
		} 
		printf("\n"); 
	} 
} 


void main(void) 
{ 
	int i,j,k,l; 

	for (i=0;i<9;i++){ 
		for (j=0;j<9;j++) map1[j]=0; 
	} 

	for(i=0;i<9;i++){ 
		for(j=0;j<9;j++){ 
			if (p[j] !=0) map1[j]=2; 
			if (p[j] ==1){ 
				map1[j]=1; 
			} 
			for(k=0;k<9;k++){ 
				if(map1[k][j] ==0) map1[k][j]=2; 
				if(map1[k] ==0) map1[k]=2; 
			} 
/* 			for (i=0;i<7;i+3){ 
				for (j=0;j<7;j+3){ 
					for(k=i;k<k+3;k++){ 
						for(l=j;l<l+3;l++){ 
						} 
					} 
				} 
			} 
 */		} 
	 
	}
	disp();
	printf("\n");
	disp_2();
} 
**------**

**実行結果**

0 0 6 0 0 0 0 0 1
0 7 0 0 6 0 0 5 0
8 0 0 1 0 3 2 0 0
0 0 5 0 4 0 8 0 0
0 4 0 7 0 2 0 9 0
0 0 8 0 1 0 7 0 0
0 0 1 2 0 5 0 0 3
0 6 0 0 7 0 0 8 0
2 0 0 0 0 0 4 0 0

2 2 2 2 2 2 2 2 1
2 2 2 2 2 2 2 2 2
2 2 2 1 2 2 2 2 2
2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2
2 2 2 2 1 2 2 2 2
2 2 1 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2

**-------**

何を求めているかは良く分かりませんが、、、

>どうやって0に1を入れていいのかというところで躓いています
0がありませんが、どうすればよいでしょうか?

多分
	for(k=0;k<9;k++){ 
		if(map1[k][j] ==0) map1[k][j]=2; 
		if(map1[k] ==0) map1[i][k]=2; 
	}
	
これが悪さの原因ですよ
これを消すと・・・
実行結果:disp_2
0 0 2 0 0 0 0 0 1
0 2 0 0 2 0 0 2 0
2 0 0 1 0 2 2 0 0
0 0 2 0 2 0 2 0 0
0 2 0 2 0 2 0 2 0
0 0 2 0 1 0 2 0 0
0 0 1 2 0 2 0 0 2
0 2 0 0 2 0 0 2 0
2 0 0 0 0 0 2 0 0
** ここまで **

こういうのを出したかったのではないかと思うのですがどうでしょう?
もしこのような考えなら後はif文で終わっちゃうかとw(やってないけどww

違ったら、ごめんなさい^^;

Re:数独について

#4

投稿記事 by » 18年前

作ってみたんですが…正解が出てきませんorz
どこかで凄い勘違いをしていそうなんですが…
どうすればいいんだーーーーorz

K-I

Re:数独について

#5

投稿記事 by K-I » 18年前

お返事ありがとうございます!
もう少し詳しくのせるべきでした すみません
PCが使える状態になりましたら また書き込みたいと思います 夕方になってしまうと思うんですが できればアドバイスよろしくお願いしますm(_ _)m

Re:数独について

#6

投稿記事 by » 18年前

こちらこそお願いします。

どうにも解法が思いつけない状態でして、手詰まってしまいました。
書き込みお待ちしています。

こちらは帰りが夜中になりそうなので、時間が無くほとんどできないかもしれないので、
急がれなくても良いかと思います。

K-I

Re:数独について

#7

投稿記事 by K-I » 18年前

#include <stdio.h>
int map1[9][9];
/* m:Mondai */
int p[9][9]={{0,0,6,0,0,0,0,0,1},
	         {0,7,0,0,6,0,0,5,0},
	   	     {8,0,0,1,0,3,2,0,0},
		     {0,0,5,0,4,0,8,0,0},
		     {0,4,0,7,0,2,0,9,0},
		     {0,0,8,0,1,0,7,0,0},
		     {0,0,1,2,0,5,0,0,3},
		     {0,6,0,0,7,0,0,8,0},
		     {2,0,0,0,0,0,4,0,0}};
void disp()
{	int i,j;
	for (i=0;i<9;i++){
		for (j=0;j<9;j++){
			printf("%2d",map1[j]);
		}
		printf("\n");
	}
}

void main(void)
{
	int i,j,k;       
	   

	for (i=0;i<9;i++){
		for (j=0;j<9;j++) map1[j]=0;
	}
	    
	for (i=0;i<9;i++){
		for (j=0;j<9;j++){
			if (p[j] !=0) map1[j]=2;
			if (p[j] ==1){	map1[j]=1;
				for(k=0;k<9;k++){
					if(map1[k][j] ==0) map1[k][j]=2;
					if(map1[k] ==0) map1[k]=2;
				
		
			}
		}}
	}
	disp();

}


表示結果

2 2 2 2 2 2 2 2 1
0 2 2 2 2 0 0 2 2
2 2 2 1 2 2 2 2 2
0 0 2 2 2 0 2 0 2
0 2 2 2 2 2 0 2 2
2 2 2 2 1 2 2 2 2
2 2 1 2 2 2 2 2 2
0 2 2 2 2 0 0 2 2
2 0 2 2 2 0 2 0 2

となって3*3左上で言うと

2 2 2
0 2 2
2 2 2

この部分なんですがこの0にはかならず1が入るんですが一番最初の

for (i=0;i<7;i+3){
		for (j=0;j<7;j+3){
			for(k=i;k<k+3;k++){
				for(l=j;l<l+3;l++){


で3*3ますずつ調べてその後2が7個0が1個の場合0を1にするというのをどうしたらいいかで躓いています また説明下手ですみません Countを使ってみたらといわれたんですが 私の本にはCountが載っていなくて・・・
自分なりにやっていますが多分まだ解決しそうにないので どうかアドバイスのほうお願いします

Re:数独について

#8

投稿記事 by » 18年前

実行結果
2 2 2 2 2 2 2 2 1
0 2 2 2 2 0 0 2 2
2 2 2 1 2 2 2 2 2
0 0 2 2 2 0 2 0 2
0 2 2 2 2 2 0 2 2
2 2 2 2 1 2 2 2 2
2 2 1 2 2 2 2 2 2
0 2 2 2 2 0 0 2 2
2 0 2 2 2 0 2 0 2

0 0 6 0 0 0 0 0 1
0 7 0 0 6 1 1 5 0
8 0 0 1 0 3 2 0 0
0 0 5 0 4 1 8 0 0
0 4 0 7 0 2 0 9 0
0 0 8 0 1 0 7 0 0
0 0 1 2 0 5 0 0 3
0 6 0 0 7 0 0 8 0
2 0 0 0 0 0 4 0 0

一様 0が1 2が7 はできました。
2が8じゃないのは何でなんでしょうか?

作れましたが、説明は苦手なので、解読お願いします。
どこが何してるか不明ってところがあれば聞いていただければお答えします。

がんばってください。

K-I

Re:数独について

#9

投稿記事 by K-I » 18年前

お忙しいのにありがとうございます!
すみません 3*3=9なのだから0が1つ 2が8こでした
3*3のマスには同じ数字が入ることがないので

2 2 2
0 2 2
2 2 2

の場合0に1が入るでした 結果が

2 2 2 2 2 2 2 2 1
0 2 2 2 2 0 0 2 2
2 2 2 1 2 2 2 2 2
0 0 2 2 2 0 2 0 2
0 2 2 2 2 2 0 2 2
2 2 2 2 1 2 2 2 2
2 2 1 2 2 2 2 2 2
0 2 2 2 2 0 0 2 2
2 0 2 2 2 0 2 0 2

↑これから

2 2 2 2 2 2 2 2 1
1 2 2 2 2 0 0 2 2
2 2 2 1 2 2 2 2 2
0 0 2 2 2 0 2 0 2
0 2 2 2 2 2 0 2 2
2 2 2 2 1 2 2 2 2
2 2 1 2 2 2 2 2 2
0 2 2 2 2 0 0 2 2
2 0 2 2 2 0 2 0 2

こうするにはどうしようという質問でした
間違えてしまい申し訳ありません

K-I

Re:数独について

#10

投稿記事 by K-I » 18年前

雷さん すばらしいです!雷さんのでいけると思います!
でも自分のやつの続きに加えていかないとならないのでつなげてみたんですが1が代入されません なぜでしょうか?
#include <stdio.h>
int map1[9][9];
/* m:Mondai */
int p[9][9]={{0,0,6,0,0,0,0,0,1},
	         {0,7,0,0,6,0,0,5,0},
	   	     {8,0,0,1,0,3,2,0,0},
		     {0,0,5,0,4,0,8,0,0},
		     {0,4,0,7,0,2,0,9,0},
		     {0,0,8,0,1,0,7,0,0},
		     {0,0,1,2,0,5,0,0,3},
		     {0,6,0,0,7,0,0,8,0},
		     {2,0,0,0,0,0,4,0,0}};
void disp()
{	int i,j;
	for (i=0;i<9;i++){
		for (j=0;j<9;j++){
			printf("%2d",p[j]);
		}
		printf("\n");	
}
}
void main(void)
{
	int i,j,k;
	int x,y;	//ブロック移動用
	int count_0, count_2;	//個数を数える用
	int set;	
	int r,s,t=3;	// t は足す数、 r,s はx,y の3倍  
	    
	   

	for (i=0;i<9;i++){
		for (j=0;j<9;j++) map1[j]=0;
	}
	  
	  for(i=0;i<9;i++){
	  	for(j=0;j<9;j++){
			if (p[j] !=0) map1[j]=2;
			if (p[j] ==1){
				map1[j]=1;
				for(k=0;k<9;k++){
					if(map1[k][j] ==0) map1[k][j]=2;
					if(map1[k] ==0) map1[k]=2;
				}
for(x=0; x<3; x++){
		for(y=0; y<3; y++){
			r=x*3;
			s=y*3;
				count_0=0;
				count_2=0;
				for(i=r; i<r+t; i++){
					for(j=s; j<s+t; j++){
						if( map1[j] == 0)
							count_0 +=1;
						else if( map1[j] == 2 )
							count_2 +=1;
					}
				}
				
				if( (count_0 == 1) && (count_2 == 8)){	
					for(i=r; i<r+t; i++){
						for(j=s; j<s+t; j++){
							if( map1[i][j] == 0){
								p[i][j] = 1;
				}
		}}				}
		}	}	}}
	disp();
}
}


表示結果

0 0 6 0 0 0 0 0 1
0 7 0 0 6 0 0 5 0
8 0 0 1 0 3 2 0 0
0 0 5 0 4 0 8 0 0
0 4 0 7 0 2 0 9 0
0 0 8 0 1 0 7 0 0
0 0 1 2 0 5 0 0 3
0 6 0 0 7 0 0 8 0
2 0 0 0 0 0 4 0 0

もうなにがなんやら・・ あと雷さんはどんな勉強法をしていますか?参考までに教えていただけるとありがたいのですが

Re:数独について

#11

投稿記事 by » 18年前

>でも自分のやつの続きに加えていかないとならないのでつなげてみたんですが1が代入されません なぜでしょうか?

何故だと思いますか?
まず、どこで1が代入(でいいのかな?)されているか分かりますか?
その関数はどこで宣言されていますか?
その値は何が入っていますか?

それと、『自分のやつの続きに加えていかないとならない』ですが、関数を使えるようになったほうが良いと思います。
K-Iさんのプログラムは for文の中に for文が入っていてとても見にくいですよね?
これを解消するために関数を使います。
そうすると、上で投げかけている質問の答えが一瞬で分かります。
僕もまだまだなのですが、ばらばらにするべきところを見極めて実行できると、とても見やすいものが出来上がります。
これによりバグが出にくくなるはずです。

関数化はLvが一段あがるものと僕は考えています。
なので、今のmain関数をバラバラに関数化してみてください。
かなりの重労働に感じるでしょう。
でも、それこそが良い勉強になると思います。
つまり、

>雷さんはどんな勉強法をしていますか?参考までに教えていただけるとありがたいのですが

これが僕の勉強方みたいなものです。(ぇ

本やサイトなどを見ながらプログラムを作りますよね?
その時、コピー&ペーストは極力控えるのです。
そうすると、何故か本当に何故か知りませんが、なんとなく頭に入ってきているのです。
改造したい時にこの辺を変えれば良いんじゃないかな?
と、あたりがつけやすく感じるのです。

もちろんめちゃくちゃ面倒で、したくありません。

他の方々ならもっと良い方法を使用しているかもしれません。
でも、僕は記憶力が悪いので(orz)この方法が一番あっていると感じます。

と、言ってもつまらないものは詰まらないんです。
なので、今回のように作ってみたいな~っと思ったものを一様完成まで持っていくのです。
その後で、色々な効果、機能を追加していく。
面白いし、勉強になると思います。

こうしたい!こうやって見たがうまくいかなかった。
などというのが合ったら、相談してください。
頑張って分かる限り答えます。
でも、僕も未だに基礎がおろそかな者です。
このサイトには良い方々(神の様な)が居られます。
その方達の注意をちゃんと聞いていけば、僕などすぐに抜かれてしまうかもしれません。
そうならないように頑張りますがw

ただ、今回のプログラムで僕よりもうまいところがあり、勉強させてもらっているものでよければですがw

偉そうに言うことと長文失礼しました。

Re:数独について

#12

投稿記事 by » 18年前

この方法で、9回、回してみたが…
後いる条件が僕には分かりません。

0 0 6 0 2 7 0 0 1
1 7 0 0 6 0 0 5 8
8 0 0 1 0 3 2 0 0
7 0 5 0 4 0 8 0 0
0 4 0 7 8 2 0 9 0
0 0 8 0 1 0 7 0 0
0 0 1 2 0 5 0 0 3
0 6 0 0 7 0 0 8 2
2 0 0 0 0 0 4 0 0

ここから、0の場所に入れていってなり立つかどうかでも検証すれば良いのかな?
成り立つものが複数存在する可能性があるから、それぞれの番号で保存して、
全部の番号が重ならないのを呼び出せばいけそうだけど…
やりたくない;;
何か良いアルゴリズムがあればご教授下さい^^;

K-I

Re:数独について

#13

投稿記事 by K-I » 18年前

雷さん返信ありがとうございます!
アドバイス通りやってみます!
あと勉強法も試してみようと思います!

K-I

Re:数独について

#14

投稿記事 by K-I » 18年前

やっと出来ました!力技でやったのでまだ改良しなくちゃいけませんが 表示結果も正しい答えが表示されて もう感激です;;
雷さんやこの掲示板を作ってくださった管理人さんやみなさんのおかげでプログラムが面白くなってきました!
また何かあったらアドバイスお願いします^^

閉鎖

“C言語何でも質問掲示板” へ戻る