MicroMouse Maze Library  3703225
関数
main.cpp ファイル

迷路探索アルゴリズムの使用例 [詳解]

#include <algorithm>
#include <thread>
#include "MazeLib/Maze.h"
#include "MazeLib/StepMap.h"
main.cpp の依存先関係図:

関数

void MoveRobot (const Direction relativeDir)
 ロボットを動かす模擬関数 [詳解]
 
void ShowAnimation (const StepMap &stepMap, const Maze &maze, const Position &pos, const Direction &dir, const std::string &msg)
 アニメーション状に迷路を表示する関数 [詳解]
 
int SearchRun (Maze &maze, const Maze &mazeTarget)
 探索走行のアルゴリズム [詳解]
 
int ShortestRun (const Maze &maze)
 最短走行のアルゴリズム [詳解]
 
int main (void)
 main 関数 [詳解]
 

詳解

迷路探索アルゴリズムの使用例

著者
Ryotaro Onuki kerik.nosp@m.un11.nosp@m.+gith.nosp@m.ub@g.nosp@m.mail..nosp@m.com
日付
2019-08-29

関数詳解

◆ main()

int main ( void  )

main 関数

230  {
231  /* 画面のクリア */
232  std::cout << "\e[0;0H"; //< カーソルを左上に移動
233  std::cout << "\e[J"; //< カーソル以下を消去
234 
235  /* シミュレーションに用いる迷路の選択 */
236  const std::string filepath = "../mazedata/data/16MM2018CX.maze";
237 
238  /* 正解の迷路を用意 */
239  Maze mazeTarget;
240  /* ファイルから迷路情報を取得 */
241  if (!mazeTarget.parse(filepath.c_str())) {
242  std::cerr << "Failed to Parse Maze: " << filepath << std::endl;
243  return -1;
244  }
245  /* 正解の迷路の表示 */
246  mazeTarget.print();
247 
248  /* 探索用の迷路を用意 */
249  Maze maze;
250  /* ゴール位置を設定 */
251  maze.setGoals(mazeTarget.getGoals());
252 
253  /* 探索走行テスト */
254  SearchRun(maze, mazeTarget);
255 
256  /* 最短走行テスト */
257  ShortestRun(maze);
258 
259  /* 終了 */
260  return 0;
261 }
迷路の壁情報を管理するクラス
Definition: Maze.h:646
void setGoals(const Positions &goals)
ゴール区画の集合を更新
Definition: Maze.h:822
const Positions & getGoals() const
ゴール区画の集合を取得
Definition: Maze.h:830
void print(std::ostream &os=std::cout, const int mazeSize=MAZE_SIZE) const
迷路の表示
Definition: Maze.cpp:261
bool parse(std::istream &is)
特定の迷路の文字列(*.maze ファイル)から壁をパースする
Definition: Maze.cpp:165
int ShortestRun(const Maze &maze)
最短走行のアルゴリズム
Definition: main.cpp:199
int SearchRun(Maze &maze, const Maze &mazeTarget)
探索走行のアルゴリズム
Definition: main.cpp:65
呼び出し関係図:

◆ MoveRobot()

void MoveRobot ( const Direction  relativeDir)

ロボットを動かす模擬関数

引数
relativeDir移動方向(自己位置に対する相対方向)
29  {
30  switch (relativeDir) {
31  case Direction::Front:
32  return /* <直進の処理> */;
33  case Direction::Left:
34  return /* <左ターンの処理> */;
35  case Direction::Right:
36  return /* <右ターンの処理> */;
37  case Direction::Back:
38  return /* <引き返しの処理> */;
39  default:
40  MAZE_LOGE << "invalid direction: " << relativeDir << std::endl;
41  return;
42  }
43 }
#define MAZE_LOGE
Definition: Maze.h:78

◆ SearchRun()

int SearchRun ( Maze maze,
const Maze mazeTarget 
)

探索走行のアルゴリズム

65  {
66  /* 探索テスト */
67  StepMap stepMap; //< 経路導出に使用するステップマップ
68  /* 現在方向は、現在区画に向かう方向を表す。
69  * 現在区画から出る方向ではないことに注意する。
70  * +---+---+---+ 例
71  * | < | <--- (0, 2, West)
72  * + +---+ ^ + <--- (2, 2, North)
73  * | > | <--- (1, 1, East)
74  * + +---+ v + <--- (2, 0, South)
75  * | S | | <--- (0, 0)
76  * +---+---+---+
77  */
78  Position currentPos = Position(0, 0); //< 現在の区画位置
79  Direction currentDir = Direction::North; //< 現在向いている方向
80  /* 1. ゴールへ向かう探索走行 */
81  while (1) {
82  /* 壁を確認。ここでは mazeTarget を参照しているが、実際には壁を見る */
83  const bool wall_front =
84  mazeTarget.isWall(currentPos, currentDir + Direction::Front);
85  const bool wall_left =
86  mazeTarget.isWall(currentPos, currentDir + Direction::Left);
87  const bool wall_right =
88  mazeTarget.isWall(currentPos, currentDir + Direction::Right);
89  /* 迷路の壁を更新 */
90  maze.updateWall(currentPos, currentDir + Direction::Front, wall_front);
91  maze.updateWall(currentPos, currentDir + Direction::Left, wall_left);
92  maze.updateWall(currentPos, currentDir + Direction::Right, wall_right);
93  /* 現在地のゴール判定 */
94  const auto& goals = maze.getGoals();
95  if (std::find(goals.cbegin(), goals.cend(), currentPos) != goals.cend())
96  break;
97  /* 現在地からゴールへの移動経路を、未知壁はないものとして導出 */
98  const auto moveDirs = stepMap.calcShortestDirections(
99  maze, currentPos, maze.getGoals(), false, true);
100  /* エラー処理 */
101  if (moveDirs.empty()) {
102  MAZE_LOGE << "Failed to Find a path to goal!" << std::endl;
103  return -1;
104  }
105  /* 未知壁のある区画に当たるまで進む */
106  for (const auto nextDir : moveDirs) {
107  /* 未知壁があったら終了 */
108  if (maze.unknownCount(currentPos)) break;
109  /* ロボットを動かす */
110  const auto relativeDir = Direction(nextDir - currentDir);
111  MoveRobot(relativeDir);
112  /* 現在地を進める */
113  currentPos = currentPos.next(nextDir);
114  currentDir = nextDir;
115  /* アニメーション表示 */
116  ShowAnimation(stepMap, maze, currentPos, currentDir,
117  "Searching for Goal");
118  }
119  }
120  /* 2. 最短経路上の未知区画をつぶす探索走行 */
121  while (1) {
122  /* 壁を確認。ここでは mazeTarget を参照しているが、実際には壁を見る */
123  const bool wall_front =
124  mazeTarget.isWall(currentPos, currentDir + Direction::Front);
125  const bool wall_left =
126  mazeTarget.isWall(currentPos, currentDir + Direction::Left);
127  const bool wall_right =
128  mazeTarget.isWall(currentPos, currentDir + Direction::Right);
129  /* 迷路の壁を更新 */
130  maze.updateWall(currentPos, currentDir + Direction::Front, wall_front);
131  maze.updateWall(currentPos, currentDir + Direction::Left, wall_left);
132  maze.updateWall(currentPos, currentDir + Direction::Right, wall_right);
133  /* 最短経路上の未知区画を洗い出し */
134  const auto shortestDirs = stepMap.calcShortestDirections(
135  maze, maze.getStart(), maze.getGoals(), false, false);
136  Positions shortestCandidates;
137  auto pos = maze.getStart();
138  for (const auto nextDir : shortestDirs) {
139  pos = pos.next(nextDir);
140  if (maze.unknownCount(pos)) shortestCandidates.push_back(pos);
141  }
142  /* 最短経路上に未知区画がなければ次へ */
143  if (shortestCandidates.empty()) break;
144  /* 現在地から最短候補への移動経路を未知壁はないものとして導出 */
145  const auto moveDirs = stepMap.calcShortestDirections(
146  maze, currentPos, shortestCandidates, false, true);
147  /* エラー処理 */
148  if (moveDirs.empty()) {
149  MAZE_LOGE << "Failed to Find a path to goal!" << std::endl;
150  return -1;
151  }
152  /* 未知壁のある区画に当たるまで進む */
153  for (const auto nextDir : moveDirs) {
154  /* 未知壁があったら終了 */
155  if (maze.unknownCount(currentPos)) break;
156  /* ロボットを動かす */
157  const auto relativeDir = Direction(nextDir - currentDir);
158  MoveRobot(relativeDir);
159  /* 現在地を進める */
160  currentPos = currentPos.next(nextDir);
161  currentDir = nextDir;
162  /* アニメーション表示 */
163  ShowAnimation(stepMap, maze, currentPos, currentDir,
164  "Searching for Shortest Path Candidates");
165  }
166  }
167  /* 3. スタート区画へ戻る走行 */
168  while (1) {
169  /* 現在地のスタート区画判定 */
170  if (currentPos == maze.getStart()) break;
171  /* 現在地からスタートへの最短経路を既知壁のみの経路で導出 */
172  const auto moveDirs = stepMap.calcShortestDirections(
173  maze, currentPos, {maze.getStart()}, true, true);
174  /* エラー処理 */
175  if (moveDirs.empty()) {
176  MAZE_LOGE << "Failed to Find a path to goal!" << std::endl;
177  return -1;
178  }
179  /* 経路上を進む */
180  for (const auto nextDir : moveDirs) {
181  /* ロボットを動かす */
182  const auto relativeDir = Direction(nextDir - currentDir);
183  MoveRobot(relativeDir);
184  /* 現在地を進める */
185  currentPos = currentPos.next(nextDir);
186  currentDir = nextDir;
187  /* アニメーション表示 */
188  ShowAnimation(stepMap, maze, currentPos, currentDir,
189  "Going Back to Start");
190  }
191  }
192  /* 正常終了 */
193  return 0;
194 }
迷路上の方向を表す。
Definition: Maze.h:145
const Position & getStart() const
スタート区画を取得
Definition: Maze.h:834
bool updateWall(const Position p, const Direction d, const bool b, const bool pushRecords=true)
既知の壁情報と照らしあわせながら、壁を更新する関数
Definition: Maze.cpp:130
int8_t unknownCount(const Position p) const
引数区画に隣接する未知壁の数を返す
Definition: Maze.cpp:125
bool isWall(const WallIndex i) const
壁の有無を返す
Definition: Maze.h:669
区画ベースのステップマップを管理するクラス
Definition: StepMap.h:19
Directions calcShortestDirections(const Maze &maze, const Position start, const Positions &dest, const bool knownOnly, const bool simple)
与えられた区画間の最短経路を導出する関数
Definition: StepMap.cpp:221
void MoveRobot(const Direction relativeDir)
ロボットを動かす模擬関数
Definition: main.cpp:29
void ShowAnimation(const StepMap &stepMap, const Maze &maze, const Position &pos, const Direction &dir, const std::string &msg)
アニメーション状に迷路を表示する関数
Definition: main.cpp:52
std::vector< Position > Positions
Position 構造体の動的配列、集合
Definition: Maze.h:375
迷路の区画の位置(座標)を定義。
Definition: Maze.h:268
Position next(const Direction d) const
自分の引数方向に隣接した区画の Position を返す
Definition: Maze.cpp:22
呼び出し関係図:

◆ ShortestRun()

int ShortestRun ( const Maze maze)

最短走行のアルゴリズム

199  {
200  /* スタートからゴールまでの最短経路導出 */
201  StepMap stepMap;
202  const auto shortestDirs = stepMap.calcShortestDirections(
203  maze, maze.getStart(), maze.getGoals(), true, false);
204  if (shortestDirs.empty()) {
205  MAZE_LOGE << "Failed to Find a path to goal!" << std::endl;
206  return -1;
207  }
208  /* 最短走行 */
209  Position currentPos = maze.getStart();
210  Direction currentDir = Direction::North;
211  for (const auto nextDir : shortestDirs) {
212  /* ロボットを動かす */
213  const auto relativeDir = Direction(nextDir - currentDir);
214  MoveRobot(relativeDir);
215  /* 現在地を進める */
216  currentPos = currentPos.next(nextDir);
217  currentDir = nextDir;
218  /* アニメーション表示 */
219  ShowAnimation(stepMap, maze, currentPos, currentDir, "Shortest Run");
220  }
221  /* 最短経路の表示 */
222  maze.print(shortestDirs);
223  /* 終了 */
224  return 0;
225 }
呼び出し関係図:

◆ ShowAnimation()

void ShowAnimation ( const StepMap stepMap,
const Maze maze,
const Position pos,
const Direction dir,
const std::string &  msg 
)

アニメーション状に迷路を表示する関数

引数
stepMap表示するステップマップ
maze表示する迷路
pos迷路上の位置
dir進行方向
54  {
55  std::cout << "\e[0;0H"; //< カーソルを左上に移動
56  stepMap.print(maze, pos, dir);
57  std::cout << "\e[J"; //< カーソル以下を消去
58  std::cout << msg << std::endl;
59  std::this_thread::sleep_for(std::chrono::milliseconds(10));
60 }
void print(const Maze &maze, const Position p=Position(-1, -1), const Direction d=Direction::Max, std::ostream &os=std::cout) const
ステップの表示
Definition: StepMap.cpp:21
呼び出し関係図: