str/apps/explorer/PuzzleExplorer.cpp (125 lines of code) (raw):
#include "PuzzleExplorer.h"
// コンストラクタ
PuzzleExplorer::PuzzleExplorer()
{
myPosition = 0;
}
// デストラクタ
PuzzleExplorer::~PuzzleExplorer(){}
// ブロック並べエリアのマップ、ブロックの初期配置などの初期設定
void PuzzleExplorer::init(int *blockPositions)
{
//機体初期位置10
setMyPosition(10);
// ノードの設定
setNodes();
//ブロックの位置設定
setBlocks(blockPositions);
// 隣接ノード設定
setNeighborNode();
}
// 現在地の変更
void PuzzleExplorer::setMyPosition(int num)
{
myPosition = num;
return;
}
// ノードの設定(位置番号、色、位置座標)
void PuzzleExplorer::setNodes()
{
for(int i=0; i<16; i++)
{
Node node;
node.setNum(i);
node.setColor();
node.setPosition(nodePositionList[i][0], nodePositionList[i][1]);
nodeList[i] = node;
}
}
// ブロック設定
void PuzzleExplorer::setBlocks(int *blockPositions)
{
for(int i=0; i<5; i++)
{
Block block(blockPositions[i]);
blockList[i] = block;
// ブロックを持つノード設定
nodeList[blockPositions[i]].setHasBlock(true);
}
blockList[0].setColor(BlockColor::Black);
blockList[1].setColor(BlockColor::Red);
blockList[2].setColor(BlockColor::Yellow);
blockList[3].setColor(BlockColor::Blue);
blockList[4].setColor(BlockColor::Green);
return;
}
// 隣接ノードの設定
void PuzzleExplorer::setNeighborNode()
{
//nodeListから隣接ノードを取得
for(int i=0; i<16;i++)
{
Node* neighbor[5] = {};
for(int j=0; j<5; j++)
{
// 隣接ノード番号が-1の時(隣接ノードがないとき)nullポインタを入れる
if(neighborList[i][j] == -1)
{
neighbor[j] = nullptr;
continue;
}
Node* node = &nodeList[neighborList[i][j]];
neighbor[j] = node;
}
nodeList[i].setNeighbor(neighbor);
neighbor[5] = {};
}
return;
}
// 位置番号からノードの色を返す
BlockColor PuzzleExplorer::getNodeColor(int num)
{
return nodeList[num].getColor();
}
// 現在地の隣接ノード取得
Node** PuzzleExplorer::getMyNeighbor()
{
return nodeList[myPosition].getNeighbor();
}
// 現地点から最寄りのブロックの位置を返す
int PuzzleExplorer::getNearestBlockPosition()
{
Node node = nodeList[myPosition];
queue<Node> que;
// ブロックを持つノードが見つかるまで幅優先探索
while(!node.getHasBlock())
{
Node** nodes = node.getNeighbor();
// 隣接ノードをキューに格納
for(int i=0; i<5; i++){
// 隣接ノードがnullの時は飛ばす
if(nodes[i] == nullptr)continue;
que.push(*nodes[i]);
}
node = que.front();
// キューの先頭がブロックを持っていたら終了
if(que.front().getHasBlock())
{
break;
}
// 先頭要素の削除
que.pop();
}
return node.getNum();
}
// 2つのノード間の経路探索
int* PuzzleExplorer::getRoot(int startNode, int goalNode)
{
Node node = nodeList[startNode];
Node goal = nodeList[goalNode];
int i=0;
// rootに経路を格納
root[i] = node.getNum();
i++;
// ゴールノードに到着するまで探索
while(node.getNum() != goal.getNum())
{
int cost = 1000;
Node** explorerNodes = node.getNeighbor();
Node nextNode;
// 隣接ノードからゴールまでのコストが低いノードを次の探索ノードに選択
for(int j=0; j<5; j++)
{
//隣接ノードがnullの時飛ばす
if(explorerNodes[j] == nullptr)continue;
// ゴールノードまでの距離コストが小さければ更新
int neighborCost = getCost(*explorerNodes[j], goal);
if(cost > neighborCost)
{
cost = neighborCost;
nextNode = *explorerNodes[j];
}
}
root[i] = nextNode.getNum();
node = nextNode;
i++;
}
return root;
}
// ノード間の距離コストを計算
int PuzzleExplorer::getCost(Node node1, Node node2)
{
int cost = (node1.getPositionX() - node2.getPositionX())*(node1.getPositionX() - node2.getPositionX()) + (node1.getPositionY() - node2.getPositionY())*(node1.getPositionY() - node2.getPositionY());
return cost;
}