2D网格指定范围周边单元格获取问题及代码优化咨询
Fixing Your Surrounding Cells Logic
The core issue with your current code is that it's only checking cells along the 8 cardinal/intercardinal lines from your current position, not the entire rectangular area within your specified areaSize. For example, when areaSize=2, it will only pick cells that are 1 or 2 steps directly north, northeast, etc.—but misses all the cells in between that are still within the 5x5 area around your current cell.
Here's a Rewritten Solution That Covers the Entire Area:
public List<Cell> GetSurroundingCells(Coord current, GridLayer layer, int areaSize) { List<Cell> surroundingCells = new List<Cell>(); // Iterate over all x offsets from -areaSize to +areaSize for (int xOffset = -areaSize; xOffset <= areaSize; xOffset++) { // Iterate over all z offsets for each x offset for (int zOffset = -areaSize; zOffset <= areaSize; zOffset++) { // Skip the current cell itself (remove this line if you want to include it) if (xOffset == 0 && zOffset == 0) continue; // Calculate the target coordinate relative to the current cell Coord target = current.Add(new Coord(xOffset, zOffset)); // Make sure the target is within the grid bounds if (target.x >= 0 && target.x < GetWidth() && target.z >= 0 && target.z < GetHeight()) { surroundingCells.Add(GetCell(target, layer)); } } } return surroundingCells; }
Key Improvements & Explanations:
- Full Area Coverage: Instead of checking only 8 directional lines, we loop through every possible offset from
-areaSizeto+areaSizein both axes. This gives you a complete square of cells around your position (3x3 forareaSize=1, 5x5 forareaSize=2, etc.). - Bounds Validation: We ensure each target coordinate stays within your grid's width and height to prevent index out-of-range errors.
- Optional Self-Inclusion: The line skipping
xOffset=0 && zOffset=0excludes the current cell from results—delete that line if you need to include it. - Better Efficiency: Your original code iterates over every cell in the entire grid, which is slow for large grids. This version only processes the cells in your target area, cutting down on unnecessary checks.
Bonus: Alternate Distance Filters
If you ever need to filter by a specific distance metric instead of a full rectangle:
- Manhattan Distance (sum of horizontal/vertical steps): Add this inside the loops:
if (Math.Abs(xOffset) + Math.Abs(zOffset) > areaSize) continue; - Euclidean Distance (straight-line distance): Use this check instead:
if (Math.Sqrt(xOffset * xOffset + zOffset * zOffset) > areaSize) continue;
But based on your original goal, the full rectangular area approach is exactly what you need.
内容的提问来源于stack exchange,提问作者Majs
相关产品推荐
相关产品推荐

