Пример #1
0
        public void Execute()
        {
            var(startX, startY) = GridUtils.GetCoordinates(_startIndex, _gridRows);
            int bestDelta = 0, bestIndex = -1;

            for (int x = 1; x < _gridCols - 1; x++)
            {
                for (int y = 1; y < _gridRows - 1; y++)
                {
                    var index = GridUtils.GetIndex(x, y, _gridRows);
                    if (_floodState[index] != GridStateConstants.FLOODED)
                    {
                        continue;
                    }

                    var delta = Math.Abs(x - startX) + Math.Abs(y - startY);
                    if (delta <= bestDelta)
                    {
                        continue;
                    }

                    bestDelta = delta;
                    bestIndex = index;
                }
            }

            if (bestIndex == -1)
            {
                throw new IndexOutOfRangeException();
            }

            _gridState[bestIndex] = GridStateConstants.EXIT;
        }
        private void FloodFill()
        {
            // we use byte.MaxValue as an 'unset' state value
            for (int i = 0; i < _cellStack.Length; i++)
            {
                _cellStack[i] = GridStateConstants.UNSET;
            }

            for (int i = 0; i < _floodState.Length; i++)
            {
                _floodState[i] = GridStateConstants.UNSET;
            }

            // Add starting cell - must be free
            Push(_startIndex);

            do
            {
                var index = Pop();
                if (index == GridStateConstants.UNSET)
                {
                    break;
                }

                _floodState[index] = GridStateConstants.FLOODED;

                var(x, y) = GridUtils.GetCoordinates(index, _rows);
                if (GridUtils.HasOutOfBoundsNeighbour(x, y, _rows, _cols))
                {
                    continue;
                }

                // Left
                var left = GridUtils.GetIndex(x - 1, y, _rows);
                if (_gridState[left] == GridStateConstants.FREE && _floodState[left] != GridStateConstants.FLOODED)
                {
                    Push(left);
                }

                // Right
                var right = GridUtils.GetIndex(x + 1, y, _rows);
                if (_gridState[right] == GridStateConstants.FREE && _floodState[right] != GridStateConstants.FLOODED)
                {
                    Push(right);
                }

                var up = GridUtils.GetIndex(x, y + 1, _rows);
                if (_gridState[up] == GridStateConstants.FREE && _floodState[up] != GridStateConstants.FLOODED)
                {
                    Push(up);
                }

                var down = GridUtils.GetIndex(x, y - 1, _rows);
                if (_gridState[down] == GridStateConstants.FREE && _floodState[down] != GridStateConstants.FLOODED)
                {
                    Push(down);
                }
            } while (_stackCount > 0);
        }
        private void FloodGate()
        {
            for (var index = _cols; index < _gridState.Length - _cols; index++)
            {
                if (_floodState[index] != GridStateConstants.FLOODED)
                {
                    continue;
                }

                var(x, y) = GridUtils.GetCoordinates(index, _rows);
                var topLeft  = GridUtils.GetIndex(x - 1, y + 1, _rows);
                var topRight = GridUtils.GetIndex(x + 1, y - 1, _rows);
                var botLeft  = GridUtils.GetIndex(x - 1, y - 1, _rows);
                var botRight = GridUtils.GetIndex(x + 1, y - 1, _rows);

                int targetIndex;
                if (_gridState[topLeft] == GridStateConstants.FREE || _gridState[botLeft] == GridStateConstants.FREE)
                {
                    targetIndex = x - 1; // left cell
                }
                else if (_gridState[topRight] == GridStateConstants.FREE || _gridState[botRight] == GridStateConstants.FREE)
                {
                    targetIndex = x + 1; // right cell
                }
                else
                {
                    continue;
                }

                var(targetX, targetY) = GridUtils.GetCoordinates(targetIndex, _rows);
                if (GridUtils.HasOutOfBoundsNeighbour(targetX, targetY, _rows, _cols))
                {
                    continue;
                }

                //UnityEngine.Debug.Log($"index: {index} has {freeNeighbours} free neighbours, delta: {freeNeighbourIdx - index}");
                _gridState[targetIndex] = GridStateConstants.FREE;
            }
        }