- oCount = openList の要素数
- cCount = closedList 内の要素の数
タイルベースの環境で斜め移動のない A-star を実装しています。openList の最後の要素にアクセスしようとすると (oCount = 0 の場合に [oCount - 1] を使用)、openList に「範囲外のインデックス エラー」がスローされることがよくあります。ただし、oCount は cCount が 159 の場合にのみ 0 になります。これは、closedList が openList のすべての要素を使用したことを示しています。次に例を示します。
cCount が 159 になる -> oCount が 0 -> closedList[158] 内のタイルを囲むタイルを確認する -> 有効なタイルがない -> while ループの先頭に戻る -> openList の最後の要素を closedList に移動しようとする (エラー)
これが私の FindPath() メソッドです: (タイルのグリッド位置は、配列内の位置に基づいています (つまり、タイル [0,0] は左上隅のタイルです)
//xBound + yBound = the bounding area with which the character can walk
public List<int> FindPath(Tile[,] tile, Vector2 xBoundary, Vector2 yBoundary, Vector2 startTile, Vector2 endTile)
{
//Initialize variables
List<Tile> openList = new List<Tile>();
List<Tile> closedList = new List<Tile>();
List<int> path = new List<int>();
int cCount = 0;
int oCount = 0;
tile[(int)startTile.X, (int)startTile.Y].PDir = 0; //PDir = direction to its parent tile
//Add starting tile to openList
openList.Add(tile[(int)startTile.X, (int)startTile.Y]);
//Set scores for starting tile
openList[0].G = 0;
openList[0].H = (int)Math.Abs(endTile.X - startTile.X) + (int)Math.Abs(endTile.Y - startTile.Y);
openList[0].F = openList[0].G + openList[0].H;
while (path.Count == 0)
{
oCount = openList.Count;
//Sort openList by decreasing F score
openList = Sort(openList);
//Move tile with lowest F score from openList to closedList
closedList.Add(openList[oCount - 1]); //ERROR OCCURS HERE
openList.RemoveAt(oCount - 1);
cCount = closedList.Count;
//Add valid surrounding tiles OR Alter valid existing tiles
//----------------------------------------------------------------------------------------------
for (int a = -1; a < 2; a += 2) //[a = difference in grid x-position]
{
//If tile is walkable, not in closed list, and within set boundaries...
if (tile[closedList[cCount - 1].X + a, closedList[cCount - 1].Y].Collision == false
&& !closedList.Contains(tile[closedList[cCount - 1].X + a, closedList[cCount - 1].Y])
&& closedList[cCount - 1].X + a >= xBoundary.X && closedList[cCount - 1].X + a <= xBoundary.Y //Test if boundaries must be < or <=
&& closedList[cCount - 1].Y >= yBoundary.X && closedList[cCount - 1].Y <= yBoundary.Y)
{
//If tile not in open list...
if (!openList.Contains(tile[closedList[cCount - 1].X + a, closedList[cCount - 1].Y]))
{
//Add tile
openList.Add(tile[closedList[cCount - 1].X + a, closedList[cCount - 1].Y]);
oCount = openList.Count;
//Set parent direction
if (a == -1)
tile[closedList[cCount - 1].X + a, closedList[cCount - 1].Y].PDir = 1;
else if (a == 1)
tile[closedList[cCount - 1].X + a, closedList[cCount - 1].Y].PDir = 3;
//Calculate F, G and H
openList[oCount - 1].G = closedList[cCount - 1].G + 1;
openList[oCount - 1].H = (int)Math.Abs(endTile.X - openList[oCount - 1].X) + (int)Math.Abs(endTile.Y - openList[oCount - 1].Y);
openList[oCount - 1].F = openList[oCount - 1].G + openList[oCount - 1].H;
}
//otherwise, check if current path is better than the previous path that tile had...
else if (closedList[cCount - 1].G + 1 < tile[closedList[cCount - 1].X + a, closedList[cCount - 1].Y].G)
{
//Set new parent direction
if (a == -1)
tile[closedList[cCount - 1].X + a, closedList[cCount - 1].Y].PDir = 1;
else if (a == 1)
tile[closedList[cCount - 1].X + a, closedList[cCount - 1].Y].PDir = 3;
//Re-calculate G and H values
int g = closedList[cCount - 1].G + 1;
int h = (int)Math.Abs(endTile.X - tile[closedList[cCount - 1].X + a, closedList[cCount - 1].Y].X) + (int)Math.Abs(endTile.Y - tile[closedList[cCount - 1].X + a, closedList[cCount - 1].Y].Y);
//Set values to tile
tile[closedList[cCount - 1].X + a, closedList[cCount - 1].Y].G = g;
tile[closedList[cCount - 1].X + a, closedList[cCount - 1].Y].H = h;
tile[closedList[cCount - 1].X + a, closedList[cCount - 1].Y].F = g + h; //including f-value...
}
}
}
// Above for-loop repeated for [b = difference in y-position]
//----------------------------------------------------------------------------------------------
//If at endTile...
if (closedList[cCount - 1].Y == endTile.Y && closedList[cCount - 1].X == endTile.X)
{
path = PlotPath(tile, tile[(int)startTile.X, (int)startTile.Y], tile[(int)endTile.X, (int)endTile.Y]);
}
}
return path;
}
私が知る限り、これは私のアルゴリズムの問題のようです
--
- 編集 -
user3444160 のリクエストによると、スタック トレースは次のとおりです (私は信じています)。
Mini RPG (test1).exe!Mini_RPG__test1_.AI.FindPath(Mini_RPG__test1_.Tile[,] tile, Microsoft.Xna.Framework.Vector2 xBoundary, Microsoft.Xna.Framework.Vector2 yBoundary, Microsoft.Xna.Framework.Vector2 startTile, Microsoft.Xna.Framework.Vector2 endTile) Line 45 C#
Mini RPG (test1).exe!Mini_RPG__test1_.Character1.UpdateDecisions(Mini_RPG__test1_.Tile[,] tileArray) Line 106 + 0xa9 bytes C#
Mini RPG (test1).exe!Mini_RPG__test1_.Character1.Update(Microsoft.Xna.Framework.GameTime gameTime, Mini_RPG__test1_.Tile[,] tileArray) Line 69 + 0xb bytes C#
Mini RPG (test1).exe!Mini_RPG__test1_.Game1.Update(Microsoft.Xna.Framework.GameTime gameTime) Line 745 + 0x28 bytes C#
[External Code]
Mini RPG (test1).exe!Mini_RPG__test1_.Program.Main(string[] args) Line 15 + 0xb bytes C#