public static void CalculateMinimalDistancesFromGivenPosition(string[,] labyrinth, Position startPosition)
        {
            Queue<Position> positions = new Queue<Position>();
            Queue<int> distances = new Queue<int>();

            positions.Enqueue(startPosition);
            distances.Enqueue(1);

            while (positions.Count != 0)
            {
                Position currentPosition = positions.Dequeue();
                int currentDistance = distances.Dequeue();

                for (int i = 0; i < directions.GetLength(0); i++)
                {
                    Position possiblePosition = new Position();
                    possiblePosition.X = currentPosition.X + directions[i, 0];
                    possiblePosition.Y = currentPosition.Y + directions[i, 1];

                    if (IsValidMove(labyrinth, possiblePosition))
                    {
                        positions.Enqueue(possiblePosition);
                        distances.Enqueue(currentDistance + 1);
                        labyrinth[possiblePosition.X, possiblePosition.Y] = currentDistance.ToString();
                    }
                }
            }

            FillUnreachableCells(labyrinth);
        }
        private static void FillLabyrinth(string[,] labyrinth)
        {
            Position startingPosition = new Position(-1, -1);

            for (int i = 0; i < labyrinth.GetLength(0); i++)
            {
                for (int j = 0; j < labyrinth.GetLength(1); j++)
                {
                    if (labyrinth[i, j] == "*")
                    {
                        startingPosition = new Position(i, j);
                    }
                }
            }

            var queue = new Queue<Position>();
            queue.Enqueue(startingPosition);

            while (queue.Count != 0)
            {
                var position = queue.Dequeue();

                FillCell(labyrinth, position, queue);
            }

            FillUnreachableCells(labyrinth);
        }
        private static void FillCell(string[,] labyrinth, Position position, Queue<Position> queue)
        {
            var value = 1;
            int.TryParse(labyrinth[position.X, position.Y], out value);

            if (IsInRange(new Position(position.X + 1, position.Y), labyrinth) && labyrinth[position.X + 1, position.Y] == "0")
            {
                labyrinth[position.X + 1, position.Y] = (value + 1).ToString();
                queue.Enqueue(new Position(position.X + 1, position.Y));
            }

            if (IsInRange(new Position(position.X, position.Y + 1), labyrinth) && labyrinth[position.X, position.Y + 1] == "0")
            {
                labyrinth[position.X, position.Y + 1] = (value + 1).ToString();
                queue.Enqueue(new Position(position.X, position.Y + 1));
            }

            if (IsInRange(new Position(position.X - 1, position.Y), labyrinth) && labyrinth[position.X - 1, position.Y] == "0")
            {
                labyrinth[position.X - 1, position.Y] = (value + 1).ToString();
                queue.Enqueue(new Position(position.X - 1, position.Y));
            }

            if (IsInRange(new Position(position.X, position.Y - 1), labyrinth) && labyrinth[position.X, position.Y - 1] == "0")
            {
                labyrinth[position.X, position.Y - 1] = (value + 1).ToString();
                queue.Enqueue(new Position(position.X, position.Y - 1));
            }
        }
        private static bool OutOfField(Position cellPosition, char[,] labyrinth)
        {
            if (cellPosition.Column < 0 ||
                cellPosition.Column > labyrinth.GetLength(1) - 1 ||
                cellPosition.Row < 0 ||
                cellPosition.Row > labyrinth.GetLength(0) - 1)
            {
                return true;
            }

            return false;
        }
        public static Position GetStartingPoint(string[,] labyrinth)
        {
            int rows = labyrinth.GetLength(0);
            int cols = labyrinth.GetLength(1);
            Position startingPoint = new Position();

            for (int row = 0; row < rows; row++)
            {
                for (int col = 0; col < cols; col++)
                {
                    if (labyrinth[row, col] == "*")
                    {
                        startingPoint.X = row;
                        startingPoint.Y = col;
                        return startingPoint;
                    }
                }
            }

            return startingPoint;
        }
 private static void VisiteCell(char[,] labyrinth, Position visiteCellAtPosition, HashSet<Position> visited, int cellValue, Queue<QueueItem> queue, int[,] resultMovesCount)
 {
     if (!OutOfField(visiteCellAtPosition, labyrinth)
             && labyrinth[visiteCellAtPosition.Row, visiteCellAtPosition.Column] != 'x'
             && !visited.Contains(visiteCellAtPosition))
     {
         queue.Enqueue(new QueueItem { Position = visiteCellAtPosition, Value = cellValue });
         resultMovesCount[visiteCellAtPosition.Row, visiteCellAtPosition.Column] = cellValue;
         visited.Add(visiteCellAtPosition);
     }
 }
        public static void Main()
        {
            //Test labyrinth
            char[,] labyrinth =
                                 {
                {'0', '0', '0', 'x', '0', 'x'},
                {'0', 'x', '0', 'x', '0', 'x'},
                {'0', '*', 'x', '0', 'x', '0'},
                {'0', 'x', '0', '0', '0', '0'},
                {'0', '0', '0', 'x', 'x', '0'},
                {'0', '0', '0', 'x', '0', 'x'}
            };

            Position player = new Position { Row = 2, Column = 1 };
            int[,] resultMoves = new int[labyrinth.GetLength(0), labyrinth.GetLength(1)];
            Queue<QueueItem> queue = new Queue<QueueItem>();

            HashSet<Position> visited = new HashSet<Position>();

            queue.Enqueue(new QueueItem { Position = player, Value = 0 });
            visited.Add(player);

            while (queue.Count != 0)
            {
                var cell = queue.Dequeue();

                if (OutOfField(cell.Position, labyrinth))
                {
                    continue;
                }

                Position up = new Position { Row = cell.Position.Row - 1, Column = cell.Position.Column };
                Position down = new Position { Row = cell.Position.Row + 1, Column = cell.Position.Column };
                Position left = new Position { Column = cell.Position.Column - 1, Row = cell.Position.Row };
                Position right = new Position { Column = cell.Position.Column + 1, Row = cell.Position.Row };

                VisiteCell(labyrinth, up, visited, cell.Value + 1, queue, resultMoves);
                VisiteCell(labyrinth, down, visited, cell.Value + 1, queue, resultMoves);
                VisiteCell(labyrinth, left, visited, cell.Value + 1, queue, resultMoves);
                VisiteCell(labyrinth, right, visited, cell.Value + 1, queue, resultMoves);
            }

            char[,] resultLabyrinth = new char[labyrinth.GetLength(0), labyrinth.GetLength(1)];

            //Print the result
            for (var i = 0; i < resultMoves.GetLength(0); i++)
            {
                for (var j = 0; j < resultMoves.GetLength(1); j++)
                {
                    if (labyrinth[i, j] == 'x')
                    {
                        Console.Write(" X ");
                    }
                    else
                        if (labyrinth[i, j] == '*')
                    {
                        Console.Write(" * ");
                    }
                    else
                    {
                        if (resultMoves[i, j] == 0)
                        {
                            Console.Write(" U ");
                        }
                        else
                        {
                            Console.Write(" " + resultMoves[i, j] + " ");
                        }
                    }
                }

                Console.WriteLine();
            }
        }
        private static bool IsValidMove(string[,] labyrinth, Position position)
        {
            bool isValidMove = position.X >= 0 && position.X < labyrinth.GetLength(0) &&
                position.Y >= 0 && position.Y < labyrinth.GetLength(1) &&
                labyrinth[position.X, position.Y] == "0";

            return isValidMove;
        }
        private static bool IsInRange(Position position, string[,] labyrinth)
        {
            if (position.X > labyrinth.GetLength(0) - 1 || position.X < 0)
            {
                return false;
            }
            if (position.Y > labyrinth.GetLength(1) - 1 || position.Y < 0)
            {
                return false;
            }

            return true;
        }