etrobocon2018 feat.KatLab  770af34cce41ae9c30c41303275e1add2daae0c3 (with uncommitted changes)
 全て クラス 名前空間 ファイル 関数 変数 列挙型 列挙値 フレンド マクロ定義 ページ
クラス | 公開メンバ関数 | 全メンバ一覧
Explorer クラス

#include <Explorer.h>

Explorer 連携図
Collaboration graph

公開メンバ関数

 Explorer ()
 
void createBlockArea ()
 
void resetBlockArea ()
 
void setHasBlockIn (std::int8_t blockID)
 
bool hasBlock (std::int8_t id)
 
std::vector< int > searchRoute (std::int8_t start, std::int8_t end)
 
NodecalculateNeighborCost (Node *parent, std::vector< Node * > *around, std::int32_t realCost, std::int8_t end)
 
std::vector< Node * > * getBlockAreaNodeList ()
 

詳解

ルート探索クラス

ETロボコン2018における、ブロック並べエリアのブロック置き場をノードとしたルート探索を行います。 斜め移動は考慮していません。

このクラスを利用して、別のブロック並べエリアを作成する場合は、次の4つの変数値を編集してください。

Example

Explorer explorer;
explorer.createBlockArea();
explorer.resetBlockArea(); // 内部のフラグを初期化
explorer.setHasBlockIn(8);
explorer.setHasBlockIn(9);
explorer.setHasBlockIn(11);
explorer.setHasBlockIn(15);
auto route = explorer.searchRoute(8, 10); // == {8, 12, 13, 14, 10}

Explorer.h52 行目に定義があります。

構築子と解体子

Explorer::Explorer ( )
inline

デフォルトコンストラクタ

各ブロック置き場における隣接ノードIDのリスト、およびノード位置リストを作成し、そのサイズを元にノードリストを初期化しています。

Explorer.h76 行目に定義があります。

77  : blockAreaNodeList(nullptr), neighborPtrs(TOTAL_NODE_COUNT), neighborsIDList(TOTAL_NODE_COUNT)
78  {
79  // 隣接ノードIDのリスト
80  std::vector<std::array<std::int8_t, MAX_NEIGHBOR_COUNT>> neighborsIDList_{
81  { { 1, 4, EMPTY_ID, EMPTY_ID },
82  { 0, 2, 5, EMPTY_ID },
83  { 1, 3, 6, EMPTY_ID },
84  { 2, 7, EMPTY_ID, EMPTY_ID },
85 
86  { 0, 5, 8, EMPTY_ID },
87  { 1, 4, 6, 9 },
88  { 2, 5, 7, 10 },
89  { 3, 6, 11, EMPTY_ID },
90 
91  { 4, 9, 12, EMPTY_ID },
92  { 5, 8, 10, 13 },
93  { 6, 9, 11, 14 },
94  { 7, 10, 15, EMPTY_ID },
95 
96  { 8, 13, EMPTY_ID, EMPTY_ID },
97  { 9, 12, 14, EMPTY_ID },
98  { 10, 13, 15, EMPTY_ID },
99  { 11, 14, EMPTY_ID, EMPTY_ID } }
100  };
101 
102  // 相対的なノード位置のリスト
103  std::vector<std::array<std::int8_t, 2>> currentPosition
104  = { { 0, 0 }, { 1, 0 }, { 2, 0 }, { 3, 0 },
105 
106  { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 },
107 
108  { 0, 2 }, { 1, 2 }, { 2, 2 }, { 3, 2 },
109 
110  { 0, 3 }, { 1, 3 }, { 2, 3 }, { 3, 3 } };
111 
112  //
113  // 以降は触れなくてよい
114  //
115 
116  for(unsigned int i = 0; i < neighborsIDList_.size(); i++) {
117  neighborsIDList[i] = neighborsIDList_[i];
118  }
119 
120  for(unsigned int i = 0; i < neighborsIDList.size(); i++) {
121  Position position;
122  position.x = currentPosition[i][0];
123  position.y = currentPosition[i][1];
124  positionList.push_back(position);
125  }
126  }

関数詳解

Node * Explorer::calculateNeighborCost ( Node parent,
std::vector< Node * > *  around,
std::int32_t  realCost,
std::int8_t  end 
)

ブロック置き場における隣接ノードのコストを計算します

これはA*アルゴリズムで用いる再帰的な内部処理です。 searchRoute(std::int8_t, std::int8_t) でのみ利用しています。

引数
parent親ノードのポインタ
around周辺ノード
realCost実コスト
end終端ノードのノードID
戻り値
終端ノードのポインタ

Explorer.cpp85 行目に定義があります。

87 {
88  auto currentItr = blockAreaNodeList->begin() + parent->getNodeID();
89  auto endItr = blockAreaNodeList->begin() + end;
90 
91  parent->setBeClosed(true);
92 
93  for(auto itr = (*currentItr)->getNeighbors()->begin();
94  itr != (*currentItr)->getNeighbors()->end(); itr++) {
95  if((*itr)->isClosed() || (*itr) == parent->getParentNode()) continue;
96 
97  int estimatedCostX = std::abs((*endItr)->getPositionX() - (*itr)->getPositionX());
98  int estimatedCostY = std::abs((*endItr)->getPositionY() - (*itr)->getPositionY());
99  int score = realCost + estimatedCostX + estimatedCostY;
100  if((*itr)->hasBlock() && (*itr)->getNodeID() != end) score += 99;
101 
102  (*itr)->setScore(score);
103  (*itr)->setRealCost(realCost);
104  (*itr)->setParentNode(parent);
105  around->push_back((*itr));
106  }
107 
108  std::int32_t min = 999;
109  std::int32_t minCost = 999;
110  Node* minNode = nullptr;
111 
112  for(auto itr = around->begin(); itr != around->end(); itr++) {
113  if((*itr)->isClosed() || (*itr) == parent->getParentNode()) continue;
114 
115  int score = (*itr)->getScore();
116  if(score > min || (score == min && (*itr)->getRealCost() >= minCost)) continue;
117 
118  min = score;
119  minCost = (*itr)->getRealCost();
120  minNode = (*itr);
121  }
122 
123  if(minNode->getNodeID() != end) {
124  std::int8_t cost = 0;
125  Node* node = minNode;
126  while(node->getParentNode() == nullptr) {
127  cost++;
128  node = node->getParentNode();
129  }
130  minNode = calculateNeighborCost(minNode, around, realCost + 1, end);
131  }
132 
133  return minNode;
134 }
Node * getParentNode()
Definition: Node.cpp:54
Definition: Node.h:142
Node * calculateNeighborCost(Node *parent, std::vector< Node * > *around, std::int32_t realCost, std::int8_t end)
Definition: Explorer.cpp:85
void setBeClosed(bool closed_)
Definition: Node.cpp:79
std::int8_t getNodeID()
Definition: Node.cpp:18
std::int32_t getScore()
Definition: Node.cpp:64

呼び出し関係図:

被呼び出し関係図:

void Explorer::createBlockArea ( )

ブロックエリアのノードリストを作成します

作成方法は、 Node クラスのドキュメントを参考にしました。

Explorer.cpp3 行目に定義があります。

4 {
5  int nodeCount = neighborsIDList.size();
6 
7  // ノードのポインタのリストを作成
8  for(int i = 0; i < nodeCount; i++) {
9  Node node;
10  node.setNodeID(i);
11  nodeList.push_back(node);
12  nodePtrs.push_back(&nodeList[i]);
13  //nodePtrs.push_back(&node);
14  }
15  // 隣接ノードのポインタのリストをノード分リスト化
16  for(int i = 0; i < nodeCount; i++) {
17  for(int nodeID : neighborsIDList[i]) {
18  if(nodeID == EMPTY_ID) break;
19  neighborPtrs[i].push_back(nodePtrs[nodeID]);
20  }
21  }
22 
23  // 隣接ノードのポインタのリストを格納
24  for(int i = 0; i < nodeCount; i++) {
25  nodePtrs[i]->setNeighbors(&neighborPtrs[i]);
26  nodePtrs[i]->setPosition(positionList[i].x, positionList[i].y);
27  }
28 
29  // 各ノードのポインタを格納
30  blockAreaNodeList = &nodePtrs;
31 }
void setNodeID(std::int8_t nodeNumber)
Definition: Node.cpp:13
Definition: Node.h:142

呼び出し関係図:

被呼び出し関係図:

std::vector< Node * > * Explorer::getBlockAreaNodeList ( )

ブロック置き場のノードのポインタのリストのポインタを取得します

戻り値
ブロック置き場のノードのポインタのリストのポインタ

Explorer.cpp136 行目に定義があります。

137 {
138  return blockAreaNodeList;
139 }

被呼び出し関係図:

bool Explorer::hasBlock ( std::int8_t  id)

ブロック置き場のノードがブロックを保持している場合は真を返す真偽値判定を行います

引数でブロックの数以上の数値を入力した場合、何かしらのエラーが発生します。 それに関する責任をこの関数は持ちません。

引数
idブロック置き場のノードID
戻り値
ブロック置き場のノードがブロックを保持している場合は真を返す真偽値

Explorer.cpp50 行目に定義があります。

51 {
52  auto itr = blockAreaNodeList->begin() + id;
53  return (*itr)->hasBlock();
54 }

被呼び出し関係図:

void Explorer::resetBlockArea ( )

ブロックエリアのノードリストにおける探索時のフラグなどを初期化します

Explorer.cpp33 行目に定義があります。

34 {
35  for(auto itr = blockAreaNodeList->begin(); itr <= blockAreaNodeList->end(); itr++) {
36  (*itr)->setBeClosed(false);
37  (*itr)->setHasBlock(false);
38  (*itr)->setScore(0);
39  (*itr)->setRealCost(0);
40  (*itr)->setParentNode(nullptr);
41  }
42 }

被呼び出し関係図:

std::vector< int > Explorer::searchRoute ( std::int8_t  start,
std::int8_t  end 
)

ブロック置き場エリアにおける移動ルートを探索します

スタート位置と向かいたい位置を入力すると、

std::vector<int>

型のリストを返します。 これは、ブロック置き場の位置コードのリストであり、隣接ノードが連なっています。 たとえば、位置コード8から位置コード10に移動したい場合は、

{8, 9, 10}

を返します。 もし位置コード9にブロックが存在している場合は、

{8, 12, 13, 14, 10}

を返します。 斜め移動は未対応です。

引数
startスタート位置の位置コード
end向かいたい位置の位置コード
戻り値
ブロック置き場の位置コードのリスト

Explorer.cpp56 行目に定義があります。

57 {
58  auto startItr = blockAreaNodeList->begin() + start;
59  auto endItr = blockAreaNodeList->begin() + end;
60 
61  int estimatedCostX = std::abs((*endItr)->getPositionX() - (*startItr)->getPositionX());
62  int estimatedCostY = std::abs((*endItr)->getPositionY() - (*startItr)->getPositionY());
63  int score = estimatedCostX + estimatedCostY;
64  if((*startItr)->hasBlock()) score += 99;
65 
66  (*startItr)->setScore(score);
67  (*startItr)->setRealCost(0);
68  (*startItr)->setParentNode(nullptr);
69 
70  std::vector<Node*> around;
71  Node* endNode = calculateNeighborCost((*startItr), &around, 1, end);
72 
73  std::vector<int> route = { endNode->getNodeID() };
74  Node* parent = endNode->getParentNode();
75  while(parent != nullptr) {
76  route.push_back(parent->getNodeID());
77  parent = parent->getParentNode();
78  }
79 
80  std::reverse(route.begin(), route.end());
81 
82  return route;
83 }
Node * getParentNode()
Definition: Node.cpp:54
Definition: Node.h:142
Node * calculateNeighborCost(Node *parent, std::vector< Node * > *around, std::int32_t realCost, std::int8_t end)
Definition: Explorer.cpp:85
std::int8_t getNodeID()
Definition: Node.cpp:18

呼び出し関係図:

被呼び出し関係図:

void Explorer::setHasBlockIn ( std::int8_t  blockID)

ブロックが存在するブロック置き場の位置コードを設定します

引数
blockIDブロック置き場の位置コード

Explorer.cpp44 行目に定義があります。

45 {
46  auto itr = blockAreaNodeList->begin() + blockID;
47  (*itr)->setHasBlock(true);
48 }

被呼び出し関係図:


このクラス詳解は次のファイルから抽出されました: