A*探索

「A*探索」の編集履歴(バックアップ)一覧はこちら

A*探索」(2015/04/05 (日) 17:57:27) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

出典 http://qiita.com/2dgames_jp/items/f29e915357c1decbc4b7 /// A-starノード. class ANode { enum eStatus { None, Open, Closed, } /// ステータス eStatus _status = eStatus.None; /// 実コスト int _cost = 0; /// ヒューリスティック・コスト int _heuristic = 0; /// 親ノード ANode _parent = null; /// 座標 int _x = 0; int _y = 0; public int X { get { return _x; } } public int Y { get { return _y; } } public int Cost { get { return _cost; } } /// コンストラクタ. public ANode(int x, int y) { _x = x; _y = y; } /// スコアを計算する. public int GetScore() { return _cost + _heuristic; } /// ヒューリスティック・コストの計算. public void CalcHeuristic(bool allowdiag, int xgoal, int ygoal) { if(allowdiag) { // 斜め移動あり var dx = (int)Mathf.Abs (xgoal - X); var dy = (int)Mathf.Abs (ygoal - Y); // 大きい方をコストにする _heuristic = dx > dy ? dx : dy; } else { // 縦横移動のみ var dx = Mathf.Abs (xgoal - X); var dy = Mathf.Abs (ygoal - Y); _heuristic = (int)(dx + dy); } Dump(); } /// ステータスがNoneかどうか. public bool IsNone() { return _status == eStatus.None; } /// ステータスをOpenにする. public void Open(ANode parent, int cost) { Debug.Log (string.Format("Open: ({0},{1})", X, Y)); _status = eStatus.Open; _cost = cost; _parent = parent; } /// ステータスをClosedにする. public void Close() { Debug.Log (string.Format ("Closed: ({0},{1})", X, Y)); _status = eStatus.Closed; } /// パスを取得する public void GetPath(List<Point2> pList) { pList.Add(new Point2(X, Y)); if(_parent != null) { _parent.GetPath(pList); } } public void Dump() { Debug.Log (string.Format("({0},{1})[{2}] cost={3} heuris={4} score={5}", X, Y, _status, _cost, _heuristic, GetScore())); } public void DumpRecursive() { Dump (); if(_parent != null) { // 再帰的にダンプする. _parent.DumpRecursive(); } } } /// A-starノード管理. class ANodeMgr { /// 地形レイヤー. Layer2D _layer; /// 斜め移動を許可するかどうか. bool _allowdiag = true; /// オープンリスト. List<ANode> _openList = null; /// ノードインスタンス管理. Dictionary<int,ANode> _pool = null; /// ゴール座標. int _xgoal = 0; int _ygoal = 0; public ANodeMgr(Layer2D layer, int xgoal, int ygoal, bool allowdiag=true) { _layer = layer; _allowdiag = allowdiag; _openList = new List<ANode>(); _pool = new Dictionary<int, ANode>(); _xgoal = xgoal; _ygoal = ygoal; } /// ノード生成する. public ANode GetNode(int x, int y) { var idx = _layer.ToIdx(x, y); if(_pool.ContainsKey(idx)) { // 既に存在しているのでプーリングから取得. return _pool[idx]; } // ないので新規作成. var node = new ANode(x, y); _pool[idx] = node; // ヒューリスティック・コストを計算する. node.CalcHeuristic(_allowdiag, _xgoal, _ygoal); return node; } /// ノードをオープンリストに追加する. public void AddOpenList(ANode node) { _openList.Add(node); } /// ノードをオープンリストから削除する. public void RemoveOpenList(ANode node) { _openList.Remove(node); } /// 指定の座標にあるノードをオープンする. public ANode OpenNode(int x, int y, int cost, ANode parent) { // 座標をチェック. if(_layer.IsOutOfRange(x, y)) { // 領域外. return null; } if(_layer.Get(x, y) > 1) { // 通過できない. return null; } // ノードを取得する. var node = GetNode(x, y); if(node.IsNone() == false) { // 既にOpenしているので何もしない return null; } // Openする. node.Open(parent, cost); AddOpenList(node); return node; } /// 周りをOpenする. public void OpenAround(ANode parent) { var xbase = parent.X; // 基準座標(X). var ybase = parent.Y; // 基準座標(Y). var cost = parent.Cost; // コスト. cost += 1; // 一歩進むので+1する. if(_allowdiag) { // 8方向を開く. for(int j = 0; j < 3; j++) { for(int i = 0; i < 3; i++) { var x = xbase + i - 1; // -1~1 var y = ybase + j - 1; // -1~1 OpenNode(x, y, cost, parent); } } } else { // 4方向を開く. var x = xbase; var y = ybase; OpenNode (x-1, y, cost, parent); // 右. OpenNode (x, y-1, cost, parent); // 上. OpenNode (x+1, y, cost, parent); // 左. OpenNode (x, y+1, cost, parent); // 下. } } /// 最小スコアのノードを取得する. public ANode SearchMinScoreNodeFromOpenList() { // 最小スコア int min = 9999; // 最小実コスト int minCost = 9999; ANode minNode = null; foreach(ANode node in _openList) { int score = node.GetScore(); if(score > min) { // スコアが大きい continue; } if(score == min && node.Cost >= minCost) { // スコアが同じときは実コストも比較する continue; } // 最小値更新. min = score; minCost = node.Cost; minNode = node; } return minNode; } }
出典 http://qiita.com/2dgames_jp/items/f29e915357c1decbc4b7 /// A-starノード. class ANode { enum eStatus { None, Open, Closed, } /// ステータス eStatus _status = eStatus.None; /// 実コスト int _cost = 0; /// ヒューリスティック・コスト int _heuristic = 0; /// 親ノード ANode _parent = null; /// 座標 int _x = 0; int _y = 0; public int X { get { return _x; } } public int Y { get { return _y; } } public int Cost { get { return _cost; } } /// コンストラクタ. public ANode(int x, int y) { _x = x; _y = y; } /// スコアを計算する. public int GetScore() { return _cost + _heuristic; } /// ヒューリスティック・コストの計算. public void CalcHeuristic(bool allowdiag, int xgoal, int ygoal) { if(allowdiag) { // 斜め移動あり var dx = (int)Mathf.Abs (xgoal - X); var dy = (int)Mathf.Abs (ygoal - Y); // 大きい方をコストにする _heuristic = dx > dy ? dx : dy; } else { // 縦横移動のみ var dx = Mathf.Abs (xgoal - X); var dy = Mathf.Abs (ygoal - Y); _heuristic = (int)(dx + dy); } Dump(); } /// ステータスがNoneかどうか. public bool IsNone() { return _status == eStatus.None; } /// ステータスをOpenにする. public void Open(ANode parent, int cost) { Debug.Log (string.Format("Open: ({0},{1})", X, Y)); _status = eStatus.Open; _cost = cost; _parent = parent; } /// ステータスをClosedにする. public void Close() { Debug.Log (string.Format ("Closed: ({0},{1})", X, Y)); _status = eStatus.Closed; } /// パスを取得する public void GetPath(List<Point2> pList) { pList.Add(new Point2(X, Y)); if(_parent != null) { _parent.GetPath(pList); } } public void Dump() { Debug.Log (string.Format("({0},{1})[{2}] cost={3} heuris={4} score={5}", X, Y, _status, _cost, _heuristic, GetScore())); } public void DumpRecursive() { Dump (); if(_parent != null) { // 再帰的にダンプする. _parent.DumpRecursive(); } } } /// A-starノード管理. class ANodeMgr { /// 地形レイヤー. Layer2D _layer; /// 斜め移動を許可するかどうか. bool _allowdiag = true; /// オープンリスト. List<ANode> _openList = null; /// ノードインスタンス管理. Dictionary<int,ANode> _pool = null; /// ゴール座標. int _xgoal = 0; int _ygoal = 0; public ANodeMgr(Layer2D layer, int xgoal, int ygoal, bool allowdiag=true) { _layer = layer; _allowdiag = allowdiag; _openList = new List<ANode>(); _pool = new Dictionary<int, ANode>(); _xgoal = xgoal; _ygoal = ygoal; } /// ノード生成する. public ANode GetNode(int x, int y) { var idx = _layer.ToIdx(x, y); if(_pool.ContainsKey(idx)) { // 既に存在しているのでプーリングから取得. return _pool[idx]; } // ないので新規作成. var node = new ANode(x, y); _pool[idx] = node; // ヒューリスティック・コストを計算する. node.CalcHeuristic(_allowdiag, _xgoal, _ygoal); return node; } /// ノードをオープンリストに追加する. public void AddOpenList(ANode node) { _openList.Add(node); } /// ノードをオープンリストから削除する. public void RemoveOpenList(ANode node) { _openList.Remove(node); } /// 指定の座標にあるノードをオープンする. public ANode OpenNode(int x, int y, int cost, ANode parent) { // 座標をチェック. if(_layer.IsOutOfRange(x, y)) { // 領域外. return null; } if(_layer.Get(x, y) > 1) { // 通過できない. return null; } // ノードを取得する. var node = GetNode(x, y); if(node.IsNone() == false) { // 既にOpenしているので何もしない return null; } // Openする. node.Open(parent, cost); AddOpenList(node); return node; } /// 周りをOpenする. public void OpenAround(ANode parent) { var xbase = parent.X; // 基準座標(X). var ybase = parent.Y; // 基準座標(Y). var cost = parent.Cost; // コスト. cost += 1; // 一歩進むので+1する. if(_allowdiag) { // 8方向を開く. for(int j = 0; j < 3; j++) { for(int i = 0; i < 3; i++) { var x = xbase + i - 1; // -1~1 var y = ybase + j - 1; // -1~1 OpenNode(x, y, cost, parent); } } } else { // 4方向を開く. var x = xbase; var y = ybase; OpenNode (x-1, y, cost, parent); // 右. OpenNode (x, y-1, cost, parent); // 上. OpenNode (x+1, y, cost, parent); // 左. OpenNode (x, y+1, cost, parent); // 下. } } /// 最小スコアのノードを取得する. public ANode SearchMinScoreNodeFromOpenList() { // 最小スコア int min = 9999; // 最小実コスト int minCost = 9999; ANode minNode = null; foreach(ANode node in _openList) { int score = node.GetScore(); if(score > min) { // スコアが大きい continue; } if(score == min && node.Cost >= minCost) { // スコアが同じときは実コストも比較する continue; } // 最小値更新. min = score; minCost = node.Cost; minNode = node; } return minNode; } }

表示オプション

横に並べて表示:
変化行の前後のみ表示: