private int _getShortestPath(int[][] arr, int[][] distances, MatrixPoint start, MatrixPoint end, int curDistance)
        {
            // if out of bounds, return
            if (start.R < 0 || start.R >= arr.Length || start.C < 0 || start.C >= arr.Length)
            {
                return(int.MaxValue);
            }

            // if already visited, return
            if (distances[start.R][start.C] != int.MaxValue)
            {
                return(int.MaxValue);
            }

            // set distance to the shortest distance to this block
            distances[start.R][start.C] = Math.Min(distances[start.R][start.C], curDistance);

            var queue = new Queue <MatrixPoint>();

            queue.Enqueue(start);             // enqueue first point

            //while (queue.Count != 0)
            //{

            //}

            // breadth first to fill out entire distances matrix
            _getShortestPath(arr, distances, new MatrixPoint(start.R + 1, start.C), end, curDistance + 1);
            _getShortestPath(arr, distances, new MatrixPoint(start.R - 1, start.C), end, curDistance + 1);
            _getShortestPath(arr, distances, new MatrixPoint(start.R, start.C + 1), end, curDistance + 1);
            _getShortestPath(arr, distances, new MatrixPoint(start.R, start.C - 1), end, curDistance + 1);

            return(distances[end.R][end.C]);
        }
        public int GetShortestPath(int[][] arr, MatrixPoint start, MatrixPoint end)
        {
            var distances = GetDistancesArray(arr);

            return(_getShortestPath(arr, distances, start, end, 0));
        }