C# 递归函数中的堆栈溢出异常错误

C# 递归函数中的堆栈溢出异常错误,c#,C#,我刚开始学习c#但是我有一些java方面的经验,所以我想做的一件事是生成一个填充了1和0的2d数组映射,并递归地检查是否有一条路径,而不踩在1上 然而,在编写代码并运行它之后,它向我显示了堆栈溢出异常错误 我哪里做错了什么 编辑:数组的末尾(在本例中,最大值为9,9的单元格(它是一个10x10数组)被设置为6作为端点) 递归方法的代码: public static int recursiveCheck(int[,] grid,int x, int y, int finalX, int final

我刚开始学习c#但是我有一些java方面的经验,所以我想做的一件事是生成一个填充了1和0的2d数组映射,并递归地检查是否有一条路径,而不踩在1上

然而,在编写代码并运行它之后,它向我显示了堆栈溢出异常错误

我哪里做错了什么

编辑:数组的末尾(在本例中,最大值为9,9的单元格(它是一个10x10数组)被设置为6作为端点)

递归方法的代码:

public static int recursiveCheck(int[,] grid,int x, int y, int finalX, int finalY, int paths)
        {
            if (grid[x, y] == 6)
            {
                paths++;
                return paths;
            }
            if ((grid[x + 1, y] != 1) && (x+1 < finalX))
                return recursiveCheck(grid, x + 1, y, finalX, finalY, paths);
            if ((grid[x, y+1] != 1) && (y+1 < finalY))
                return recursiveCheck(grid, x, y+1, finalX, finalY, paths);
            if ((grid[x - 1, y] != 1) && (x > 0))
                    return recursiveCheck(grid, x - 1, y, finalX, finalY, paths);
            if (grid[x, y - 1] != 1 && y >0)
                    return recursiveCheck(grid, x, y - 1, finalX, finalY, paths);
            return 0;
        }
公共静态int递归检查(int[,]网格,int x,int y,int finalX,int finalY,int路径)
{
if(网格[x,y]==6)
{
路径++;
返回路径;
}
如果((网格[x+1,y]!=1)和&(x+10))
返回递归检查(网格,x-1,y,finalX,finalY,路径);
如果(网格[x,y-1]!=1&&y>0)
返回递归检查(网格、x、y-1、finalX、finalY、路径);
返回0;
}
阵列初始化代码:

public static int[,] gridGen()
        {
            int[,] grid = new int[10, 10];
            Random rnd = new Random();
            int lim;
            for (int i = 0; i < 10; i++)
            {
                for (int c = 0; c < 10; c++)
                {
                    lim = rnd.Next(0, 2);
                    //Console.WriteLine($"lim: {lim} ");
                    grid[i, c] = lim;
                }
            }
            grid[0, 0] = 2;
            grid[grid.GetLength(0) - 1, grid.GetLength(1) - 1] = 6;
            for (int i = 0; i < 10; i++)
            {
                for (int c = 0; c < 10; c++)
                {
                    Console.Write(grid[i, c] + " ");
                }
                Console.WriteLine();
            }
            return grid;
        }
publicstaticint[,]gridGen()
{
int[,]grid=新的int[10,10];
随机rnd=新随机();
int lim;
对于(int i=0;i<10;i++)
{
对于(int c=0;c<10;c++)
{
lim=rnd.Next(0,2);
//Console.WriteLine($“lim:{lim}”);
网格[i,c]=lim;
}
}
网格[0,0]=2;
grid[grid.GetLength(0)-1,grid.GetLength(1)-1]=6;
对于(int i=0;i<10;i++)
{
对于(int c=0;c<10;c++)
{
Write(grid[i,c]+“”);
}
Console.WriteLine();
}
返回网格;
}

您没有记录您已经访问过的空间。因此,假设网格中有两个相邻的零,那么函数将在第一级递归中移动到一个,然后在第二级递归中移动到另一个,然后在第三级返回到第一个(即使第一级递归仍然在堆栈上),以此类推

有很多方法可以让你跟踪你已经访问过的地方。如果您希望在调用此方法时临时修改输入数组,可以在查看周围的空间之前,将当前所在的空间设置为
1

    public static int recursiveCheck(int[,] grid,int x, int y, int finalX, int finalY, int paths)
    {
        var originalValue = grid[x, y];
        if (originalValue == 6)
        {
            paths++;
            return paths;
        }
        grid[x, y] = 1; // prevent deeper recursion from coming back to this space
        if ((grid[x + 1, y] != 1) && (x+1 < finalX))
            return recursiveCheck(grid, x + 1, y, finalX, finalY, paths);
        if ((grid[x, y+1] != 1) && (y+1 < finalY))
            return recursiveCheck(grid, x, y+1, finalX, finalY, paths);
        if ((grid[x - 1, y] != 1) && (x > 0))
                return recursiveCheck(grid, x - 1, y, finalX, finalY, paths);
        if (grid[x, y - 1] != 1 && y >0)
                return recursiveCheck(grid, x, y - 1, finalX, finalY, paths);

        grid[x, y] = originalValue; // allow other path checking to revisit this space.

        return 0;
    }
公共静态int递归检查(int[,]网格,int x,int y,int finalX,int finalY,int路径)
{
var原始值=网格[x,y];
如果(原始值==6)
{
路径++;
返回路径;
}
grid[x,y]=1;//防止更深层次的递归返回到此空间
如果((网格[x+1,y]!=1)和&(x+10))
返回递归检查(网格,x-1,y,finalX,finalY,路径);
如果(网格[x,y-1]!=1&&y>0)
返回递归检查(网格、x、y-1、finalX、finalY、路径);
grid[x,y]=originalValue;//允许其他路径检查重新访问此空间。
返回0;
}
还请注意,您可能可以通过将递归颠倒一点来简化事情:立即将边界检查和墙检查作为退出标准,并将路径数纯粹用作返回值而不是输入

public static int recursiveCheck(int[,] grid, int x, int y, int finalX, int finalY)
{
    if(x < 0 || x > finalX || y < 0 || y > finalY)
    {
        return 0;
    }
    var originalValue = grid[x, y];
    if (originalValue == 1)
    {
        return 0;
    }
    if (originalValue == 6)
    {
        return 1;
    }
    grid[x, y] = 1; // prevent deeper recursion from coming back to this space
    var paths = recursiveCheck(grid, x + 1, y, finalX, finalY)
        + recursiveCheck(grid, x, y + 1, finalX, finalY)
        + recursiveCheck(grid, x - 1, y, finalX, finalY)
        + recursiveCheck(grid, x, y - 1, finalX, finalY);

    grid[x, y] = originalValue; // allow other path checking to revisit this space.

    return paths;
}
publicstaticintrecursivecheck(int[,]grid,intx,inty,intfinalx,intfinaly)
{
如果(x<0 | | x>finalX | | y<0 | | y>finalY)
{
返回0;
}
var原始值=网格[x,y];
如果(原始值==1)
{
返回0;
}
如果(原始值==6)
{
返回1;
}
grid[x,y]=1;//防止更深层次的递归返回到此空间
变量路径=递归检查(网格,x+1,y,finalX,finalY)
+递归检查(网格,x,y+1,finalX,finalY)
+递归检查(网格,x-1,y,finalX,finalY)
+递归检查(网格,x,y-1,finalX,finalY);
grid[x,y]=originalValue;//允许其他路径检查重新访问此空间。
返回路径;
}

您没有记录您已经访问过的空间。因此,假设网格中有两个相邻的零,那么函数将在第一级递归中移动到一个,然后在第二级递归中移动到另一个,然后在第三级返回到第一个(即使第一级递归仍然在堆栈上),以此类推

有很多方法可以让你跟踪你已经访问过的地方。如果您希望在调用此方法时临时修改输入数组,可以在查看周围的空间之前,将当前所在的空间设置为
1

    public static int recursiveCheck(int[,] grid,int x, int y, int finalX, int finalY, int paths)
    {
        var originalValue = grid[x, y];
        if (originalValue == 6)
        {
            paths++;
            return paths;
        }
        grid[x, y] = 1; // prevent deeper recursion from coming back to this space
        if ((grid[x + 1, y] != 1) && (x+1 < finalX))
            return recursiveCheck(grid, x + 1, y, finalX, finalY, paths);
        if ((grid[x, y+1] != 1) && (y+1 < finalY))
            return recursiveCheck(grid, x, y+1, finalX, finalY, paths);
        if ((grid[x - 1, y] != 1) && (x > 0))
                return recursiveCheck(grid, x - 1, y, finalX, finalY, paths);
        if (grid[x, y - 1] != 1 && y >0)
                return recursiveCheck(grid, x, y - 1, finalX, finalY, paths);

        grid[x, y] = originalValue; // allow other path checking to revisit this space.

        return 0;
    }
公共静态int递归检查(int[,]网格,int x,int y,int finalX,int finalY,int路径)
{
var原始值=网格[x,y];
如果(原始值==6)
{
路径++;
返回路径;
}
grid[x,y]=1;//防止更深层次的递归返回到此空间
如果((网格[x+1,y]!=1)和&(x+1public List<(int r, int c)> RecursiveCheck(int[,] grid, (int r, int c) initial, int goal)
{
    var path = new List<(int r, int c)>(new[] { initial });
    return RecursiveCheck(grid, path, goal);
}
private List<(int r, int c)> RecursiveCheck(int[,] grid, List<(int r, int c)> path, int goal)
{
    foreach (var neighbour in GetNeighbours(grid, path.Last()))
    {
        if (!path.Contains(neighbour))
        {
            var next = path.Concat(new[] { neighbour }).ToList();
            if (grid[neighbour.r, neighbour.c] == goal)
            {
                return next;
            }
            else if (grid[neighbour.r, neighbour.c] == 0)
            {
                return RecursiveCheck(grid, next, goal);
            }
        }
    }
    return new List<(int r, int c)>();
}
int[,] grid = new int[3, 5]
{
    { 0, 1, 0, 0, 0},
    { 0, 1, 0, 1, 0},
    { 0, 0, 0, 1, 6},
};

List<(int r, int c)> path = RecursiveCheck(grid, (r: 0, c: 0), 6);

Console.WriteLine(path.Count);