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

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

新規登録して質問してみよう
ただいま回答率
85.48%
アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

2335閲覧

再帰関数を利用した幅優先探索

asobinin

総合スコア69

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/01/30 10:45

map上で、プレイヤーの位置からゴールの位置までの道のりを探索するアルゴリズムを書いてみたのですが、プログラムを実行中に強制終了してしまいます。
どこでエラーになっているのか、どうすれば直るのかお教えください。

Cpp

1#include <iostream> 2using namespace std; 3 4constexpr int MAP_SIZE = 5; // マップの縦横のサイズ 5 6// mapを描画 7void display(const int map[MAP_SIZE][MAP_SIZE]) { 8 for (int y = 0; y < MAP_SIZE; y++) { 9 for (int x = 0; x < MAP_SIZE; x++) { 10 switch (map[y][x]) { 11 case 0: cout << "_"; break; 12 case 1: cout << "■"; break; 13 case 2: cout << "me"; break; 14 case 3: cout << "◆"; break; 15 } 16 } 17 cout << endl; 18 } 19} 20 21// その場所が通過できる場所か 22bool passMap(const int map[MAP_SIZE][MAP_SIZE], const int x, const int y) { 23 if (0 <= x && x < MAP_SIZE && 0 <= y && y < MAP_SIZE) { 24 switch (map[y][x]) { 25 case 1: return false; break; // ■のみ通過不可 26 default: return true; break; 27 } 28 } 29 return false; 30} 31 32// 問題のアルゴリズム 33// ゴールまでの道のりを探索する 幅優先探索 34bool searchRoute(const int map[MAP_SIZE][MAP_SIZE], int route[MAP_SIZE][MAP_SIZE], int sx, int sy, int gx, int gy) { 35 if (!passMap(map, sx, sy)) return false; 36 route[sy][sx] = 1; 37 if (sx == gx && sy == gy) return true; 38 if (searchRoute(map, route, sx, sy-1, gx, gy)) return true; 39 if (searchRoute(map, route, sx, sy+1, gx, gy)) return true; 40 if (searchRoute(map, route, sx-1, sy, gx, gy)) return true; 41 if (searchRoute(map, route, sx+1, sy, gx, gy)) return true; 42 route[sy][sx] = 0; 43 return false; 44} 45 46int main() { 47 // 0:道 1:壁 2:自分 3:ゴール 48 int map[MAP_SIZE][MAP_SIZE] = { 49 {0, 2, 0, 0, 0}, 50 {0, 0, 1, 0, 0}, 51 {0, 1, 0, 0, 0}, 52 {0, 0, 0, 1, 0}, 53 {0, 0, 1, 3, 0} 54 }; 55 56 display(map); 57 int route[MAP_SIZE][MAP_SIZE]; // 道のりを保存する配列 58 for (int i = 0; i < MAP_SIZE; i++) { 59 for (int j = 0; j < MAP_SIZE; j++) 60 route[i][j] = 0; 61 } 62 searchRoute(map, route, 1, 0, 3, 4); 63 cout << endl; 64 display(route); 65 66 return 0; 67}

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

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

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

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

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

dice142

2019/01/30 11:08

エラー文を質問文に追記してください。
asobinin

2019/01/30 11:19

エラー文は出ません・・・ 唐突に強制終了してしまいます。
guest

回答3

0

ベストアンサー

確かに途中で、突然、止まるようですね。
ちょっと途中経過を出力してみたら、
sy の値が -1 になっています。

ソースを見直してみると、sx, sy の範囲チェックが無いですね。
きっとメモリを壊しているのでしょう。

[追記]
範囲外を除くようにしてみましたが、やはり、再帰が終わらないようです。
...と初期データを見ると、スタートから、スタートに戻ってくるループがある。
これを弾くようにしないと無限ループ。。正確には、同じ場所を二度通らないようにする必要があります。

passMap() の引数に route を追加し、最初のif 文の中を以下のようにして、動作を確認。
(searchRoute()にも範囲外チェック追加あり)

C++

1 if (0 <= x && x < MAP_SIZE && 0 <= y && y < MAP_SIZE) { 2 return ((map[y][x] != 1) && (route[y][x] != 1));

遠回りなルートを通っていますが、一応、ゴールまで行くみたい。

投稿2019/01/30 14:33

編集2019/01/30 15:05
pepperleaf

総合スコア6383

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

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

asobinin

2019/01/30 15:18

無事動作しました、ありがとうございます。 幅優先探索で、一度通った場所に戻ってこないようにするというところを忘れていたみたいですね・・・ この再帰関数では、最短のルートではなく、一番最初に見つかったルートを返すので最短ではない可能性がある + 関数の呼び出しコストが掛かってしまうため、コード量が少ないという利点はありますがゲームなどでは利用しづらいもののようです。もう少し工夫しなければ実践では使える場所が限定されてしまいそうです。 協力してくださった皆様、ありがとうございました。
guest

0

再帰でメモリあふれてるのではないかと
searchRouteの終了条件確認したほうが良いと思いますね

投稿2019/01/30 14:01

iwanote

総合スコア295

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

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

asobinin

2019/01/30 14:19

やはり再帰回数の問題なのかもしれません・・・ 一度再帰を利用せずに探索関数を作ってみます。
iwanote

2019/01/30 14:51

if (searchRoute(map, route, sx, sy-1, gx, gy)) return true; if (searchRoute(map, route, sx, sy+1, gx, gy)) return true; ここでループしてる可能性とかありませんか?
guest

0

display 関数でもmain関数でも

c++

1cout << endl;

が何もコンソールに表示していないから、強制終了しているように勘違いしている可能性はありませんか?

投稿2019/01/30 12:15

kts_h

総合スコア207

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

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

asobinin

2019/01/30 12:22

cout << endl;は単なる改行文字を出力しているだけです。 強制終了はsearchRouteの実行中に発生してしまいます。
kts_h

2019/01/30 12:32

強制終了だというのは、何によって分かるのですか。
asobinin

2019/01/30 12:58

実行すると、しばらくコンソールがフリーズした後、破壊されてしまいます。 何度試しても同じ結果でした。
kts_h

2019/01/30 13:57

何が破壊されるのですか。現象を具体的に説明してもらえませんか。
otn

2019/01/30 13:59

> 破壊されてしまいます。 コンソールが閉じてしまうという意味?ちょっと想像しがたいですが。
otn

2019/01/30 14:01 編集

主観を交えずに客観的な状況を書いてください。
asobinin

2019/01/30 14:16

状況としましては、 実行→searchRouteの呼出(ここでフリーズすることは確認しました)→2~3秒コンソールがフリーズ→ ウィンドウが突然閉じるという流れです。 破壊というのは、exit(1)を呼び出したような、コンソールが異常終了してしまう状態のことを言っていました・・・ 私も主観ですが、コンソールアプリケーションでは珍しいバグだと感じました。
otn

2019/01/30 14:35

端末ウィンドウで、プログラムを起動して、そのプログラムがどうなろうが、端末まで閉じてしまうというのは非常に考えにくいです。OSはWindows? Linux? MacOS? Linux/Macで、シェルから「exec プログラム名」で起動しているわけではないですよね?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問