質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

Q&A

解決済

1回答

1312閲覧

C言語 Nクイーン問題 判定がうまくいきません

unstoppa61e

総合スコア15

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

0グッド

0クリップ

投稿2019/12/13 03:28

C言語で、チェス盤にクイーンを、互いにかち合わないように置いていくプログラムを書いています(いわゆる『Nクイーン問題』です)。

再帰的な書き方が望ましいのだとは思うのですが、まず列ごとに個別で関数を作ってみたところ、3列目でハマってしまいました。

該当のソースコード

C

1#include <stdio.h> 2 3int board[3]; 4 5void solve2() { // 2列目 6 int i, j; 7 8 for (i = 0; i < 8; i++) { 9 for (j = 0; j < 2; j++) { // 1列目と2列目との重複を判定 10 if (board[j] == i) continue; 11 if (j - board[j] == 2 - i) continue; 12 if (j + board[j] == 2 + i) continue; 13 board[2] = i; 14 for (j = 0; j < 3; j++) printf("%d ", board[j]); 15 printf("\n"); 16 } 17 } 18} 19 20void solve1() { // 1列目 21 int i, j; 22 23 for (i = 0; i < 8; i++) { 24 for (j = 0; j < 1; j++) { // 1列目との重複を判定 25 if (board[j] == i) continue; 26 if (j - board[j] == 1 - i) continue; 27 if (j + board[j] == 1 + i) continue; 28 board[1] = i; 29 solve2(); 30 } 31 } 32} 33 34void solve0() { // 0列目 35 int i; // 0列目の上から何番目のマスか 36 37 for (i = 0; i < 8; i++) { 38 board[0] = i; 39 solve1(); 40 } 41} 42 43int main(void) { solve0(); }

こちらを実行すると、出力結果が

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

と続いていき、どこを見ても1列目と2列目の判定は正しくなされているものの、3列目に出てくる数字はそれ以前の列との重なりを正しく判定してくれません。

どこが間違っているのか、いくら考えてもわからず煮詰まってしまったため、teratailに初めて投稿させて頂きました。

先輩の皆様にご教示頂けましたなら幸いです。どうぞよろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

solve2() の中でループカウンタ j が重複しています。

なお、全部見たわけではないので、他にもバグがある可能性はあります。

追記

solve1()solve2() の中の continue をすべて break に変えてください。
理由は、説明するのが面倒くさいロジックをよく考えればわかると思うので、ご自身でお考えください。

ちなみに、solve1() の方は continue のままでも正常に動作しますが、ループ回数が 1回だけだからであり、たまたまうまく行っているだけです。

追記2

break に変えた上で、以下の行を追加してください(solve1() の方も同様に)。

c

1void solve2() { 2 int i, j, k; 3 4 for (i = 0; i < 8; i++) { 5 for (j = 0; j < 2; j++) { 6 if (board[j] == i) break; 7 if (j - board[j] == 2 - i) break; 8 if (j + board[j] == 2 + i) break; 9 board[2] = i; 10 for (k = 0; k < 3; k++) printf("%d ", board[k]); 11 printf("\n"); 12 } 13 if (k < 2) continue; // この行を追加。 14 } 15}

投稿2019/12/13 04:06

編集2019/12/13 07:23
2KOH

総合スコア999

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

unstoppa61e

2019/12/13 06:29

ご回答ありがとうございます。 確かに j が重複していたのですが、そちらを以下のように変更させて頂いても、出力結果は先ほどと変わりませんでした(理解が間違っていましたならごめんなさい)。 ```c #include <stdio.h> int board[3]; void solve2() { int i, j, k; for (i = 0; i < 8; i++) { for (j = 0; j < 2; j++) { if (board[j] == i) continue; if (j - board[j] == 2 - i) continue; if (j + board[j] == 2 + i) continue; board[2] = i; for (k = 0; k < 3; k++) printf("%d ", board[k]); printf("\n"); } } } void solve1() { int i, j; for (i = 0; i < 8; i++) { for (j = 0; j < 1; j++) { if (board[j] == i) continue; if (j - board[j] == 1 - i) continue; if (j + board[j] == 1 + i) continue; board[1] = i; solve2(); } } } void solve0() { int i, j; for (i = 0; i < 8; i++) { board[0] = i; solve1(); } } int main(void) { solve0(); } ``` もしも改めてご教示頂けましたなら幸いです。
unstoppa61e

2019/12/13 07:12

改めてのご回答、感謝致します。 ご指示頂きました通り、全て continue を break に変更させて頂いたのですが、出力結果は先ほどと少し違うものになったものの、まだうまくいきませんでした。 《コード》 #include <stdio.h> int board[3]; void solve2() { int i, j, k; for (i = 0; i < 8; i++) { for (j = 0; j < 2; j++) { if (board[j] == i) break; if (j - board[j] == 2 - i) break; if (j + board[j] == 2 + i) break; board[2] = i; for (k = 0; k < 3; k++) printf("%d ", board[k]); printf("\n"); } } } void solve1() { int i, j; for (i = 0; i < 8; i++) { for (j = 0; j < 1; j++) { if (board[j] == i) break; if (j - board[j] == 1 - i) break; if (j + board[j] == 1 + i) break; board[1] = i; solve2(); } } } void solve0() { int i, j; for (i = 0; i < 8; i++) { board[0] = i; solve1(); } } int main(void) { solve0(); } 《出力結果》 0 2 1 0 2 3 0 2 4 0 2 4 0 2 5 0 2 5 0 2 6 0 2 6 0 2 7 何度もご回答頂くのは恐縮ですが、もしも再度教えを請わせて頂けましたなら幸いです。
unstoppa61e

2019/12/13 07:36

ご指示を参考にして、無事に動きました! 長らくご丁寧にお付き合い頂いてご教示くださいましたこと、心より感謝申し上げます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問