/// <summary> /// adds heapcell to the heap using the given sort-value /// </summary> /// <param name="cell">heapcell to be used</param> private void add(HeapCell <T> cell) { _Size++; if ((_Size * 2 + 1) >= _Length) { grow(_Size); } _Data[_Size] = cell; int i = _Size; //do any needed swapping while (i != 1) { //compare cells if (_Data[i].Value <= _Data[i / 2].Value) { //if i is less than i/2, swap HeapCell <T> temp = _Data[i / 2]; _Data[i / 2] = _Data[i]; _Data[i] = temp; i = i / 2; } else//otherwise break { break; } } }
public BinaryHeap(int length) { _Size = 0; _Length = length * 2 + 2; _Data = new HeapCell <T> [_Length]; for (int i = 0; i < _Length; i++) { _Data[i] = new HeapCell <T>(); } }
public HeapCell <T> removeFirst() { HeapCell <T> retVal = _Data[1]; //move last item to 1st position, reduce size by 1 _Data[1] = _Data[_Size]; _Data[_Size] = null; _Size--; int u, v; v = 1; //sort the heap while (true) { u = v; //if both children exist if ((2 * u + 1) <= _Size) { //select lowest child if (_Data[u].Value >= _Data[2 * u].Value) { v = 2 * u; } if (_Data[v].Value >= _Data[2 * u + 1].Value) { v = 2 * u + 1; } }//if only one child exists else if (2 * u <= _Size) { if (_Data[u].Value >= _Data[2 * u].Value) { v = 2 * u; } } //do we need to swap or exit? if (u != v) { HeapCell <T> temp = _Data[u]; _Data[u] = _Data[v]; _Data[v] = temp; } else { break;//we've re-sorted the heap, so exit } } return(retVal); }
/// <summary> /// /// </summary> /// <param name="size"></param> private void grow(int size) { int length = size * 2 + 2; HeapCell <T>[] data = new HeapCell <T> [length]; Array.Copy(_Data, data, _Length); _Data = data; _Length = length; return; }
/// <summary> /// finds the adjacent cells /// </summary> /// <param name="cell"></param> /// <returns></returns> private List <Cell> findAdjacentCells(Cell cell) { //setup temps Terrain terrain; List <Cell> goodAdjacents = new List <Cell>(); //search ajacent tiles for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { //skip this cell since we already have it if ((i == 0) && (j == 0)) { continue; } //get the terrain terrain = _GameMap.getTerrain((int)cell.Position.X + i, (int)cell.Position.Y + j); //); //is terrain valid? if (terrain == null) { continue; } //is it blocking? if (terrain.IsBlocking) { _BlockingSet.Add(createCell((int)cell.Position.X + i, (int)cell.Position.Y + j)); continue; } //create the cell Cell newCell = createCell((int)cell.Position.X + i, (int)cell.Position.Y + j); //if we've already got it, ignore it if (contains(newCell, _ClosedSet) >= 0) { continue; } //set its parent newCell.Parent = cell; //set its G cost since we can do that here if ((i == -1 && j == -1) || (i == -1 && j == 1) || (i == 1 && j == -1) || (i == 1 && j == 1)) { //since diagonal cell, do tests to see if its a valid move (not cutting a corner) //check UL cell if ((i == -1 && j == -1)) { if (cellIsBlocking((int)cell.Position.X, (int)cell.Position.Y - 1) && cellIsBlocking((int)newCell.Position.X + 1, (int)newCell.Position.Y)) { continue; } if (cellIsBlocking((int)cell.Position.X - 1, (int)cell.Position.Y) && cellIsBlocking((int)newCell.Position.X, (int)newCell.Position.Y + 1)) { continue; } } //check LL cell if ((i == -1 && j == 1)) { if (cellIsBlocking((int)cell.Position.X - 1, (int)cell.Position.Y) && cellIsBlocking((int)newCell.Position.X, (int)newCell.Position.Y - 1)) { continue; } if (cellIsBlocking((int)cell.Position.X, (int)cell.Position.Y + 1) && cellIsBlocking((int)newCell.Position.X + 1, (int)newCell.Position.Y)) { continue; } } //check LR cell if ((i == 1) && (j == 1)) { if (cellIsBlocking((int)cell.Position.X, (int)cell.Position.Y + 1) && cellIsBlocking((int)newCell.Position.X - 1, (int)newCell.Position.Y)) { continue; } if (cellIsBlocking((int)cell.Position.X + 1, (int)cell.Position.Y) && cellIsBlocking((int)newCell.Position.X, (int)newCell.Position.Y - 1)) { continue; } } //check UR cell if ((i == 1) && (j == -1)) { if (cellIsBlocking((int)cell.Position.X + 1, (int)cell.Position.Y) && cellIsBlocking((int)newCell.Position.X, (int)newCell.Position.Y + 1)) { continue; } if (cellIsBlocking((int)cell.Position.X, (int)cell.Position.Y - 1) && cellIsBlocking((int)newCell.Position.X - 1, (int)newCell.Position.Y)) { continue; } } //valid move, so get G cost newCell.G = diaCost + cell.G; } else { newCell.G = linCost + cell.G; } //newCell.G = linCost + cell.G; //finds this cell's cost newCell.F = findCost(newCell); //check to see if we already have this one on an open list int pos = heapContains(newCell, _OpenSet); if (pos >= 0) { Cell temp = _OpenSet[pos].Data; //is cell a better path? if (cell.G + (temp.G - temp.Parent.G) < temp.G) { temp.G -= temp.Parent.G; //yes, so update it, re-calc cost, and continue; temp.Parent = cell; temp.G += temp.Parent.G; temp.F = findCost(temp); _OpenSet[pos] = new HeapCell <Cell>(temp.F, temp); continue; } else { continue; } } //_OpenSet.add(newCell.F, newCell); //add its location to the list as a good candidate goodAdjacents.Add(newCell); } } //return list return(goodAdjacents); }