通过0 [和] 1的int [,]数组

时间:2013-04-21 18:41:31

标签: c# multidimensional-array int 2d-games

草书中的文字:较旧的条目

普通文字:最新条目

好的,所以我有一个2D数组,更具体地说是0和1。 最初这是一个BMP文件(黑色和白色),我将它转换为一个整数数组。 现在,矩阵代表一张地图,其中0是我可以站立的地方(如果你愿意的话,地板),1是深渊,或者是墙(你不能站在1)。 所以我需要经历这个随机的整数数组,但我需要能够遍历地图的所有0。 如果我不止一次访问“像素”并不重要 这有什么意义?我有一个方法可以“隐藏”地图中的4个键,我的角色必须在地图中找到它们。 我的角色只能向上,向下,向左和向右移动。不允许对角线移动,显然,也不允许传送。 到目前为止,我有这段代码:

public void goThrough(int[,] map, int[] pos)
{
    int i = pos[0], j = pos[1]  ;
    while( i < map.GetLength(0) && j < map.GetLength(1) )
    {
        int cont = 0;
        if (map[i, j] == 0) 
        { 
            if (map[i, j + 1] == 0 && cont == 0 ) { j++; cont++; }
            if (map[i + 1, j] == 0 && cont == 0) { i++; cont++; }
            if (map[i, j - 1] == 0 && cont == 0 ) { j--; cont++; }
            if (map[i - 1, j] == 0 && cont == 0 ) { i--; cont++; }
        }
        if (map[i, j] == 1)
        {
        }
    }
}

public int[] Position(int[,] map)
{
    int[] pos = { 0, 0 };

    for (int i = 0; i < map.GetLength(0) && map[pos[0], pos[1]] == 1; i++)
    {
        for (int j = 0; j < map.GetLength(1) && map[pos[0], pos[1]] == 1; j++)
        {
            pos[0] = i;
            pos[1] = j;
        }
    }
    return pos;
}

显然有一些错误。请发送一些反馈!也许对这种代码有一定经验的人可以帮助我一点:D。

Edit1:我很抱歉我没有指定语言。这是C#。 要进行快速更新: 我尝试创建另一个int [,](与第一个完全相同),每次我的“explorer”遍历任何(x,y)时,我将一个(1)添加到(第二个,复制的一个) )数组。通过这种方式,我可以创建一种方法来识别我何时完全“探索”地图。 此外,使用这个“复制”数组,如果我处于探测器之前的位置,我可以选择另一个方向(该位置在第二个数组中不会是0,实际上,每次探测器通过该位置时,它会将一(1)个加到数组中的那个位置。这个想法是让探险者在他经过同一个地点一次,两次或更多时表现得不同......但是这一切根本不起作用。我仍然得到无尽的循环......

EDIT2:现在我有了这段代码:

    public void goThrough(int[,] map, int[] pos, bool[,] visited)
    {
        int x = pos[0];
        int y = pos[1];
        visited[x, y] = true;
        Console.WriteLine("Position -> Column: {0} || Row: {1}", x, y);
        // ShowAtPosition(x, y)
        if (y > 0 && map[x, y - 1] == 0 && !visited[x, y - 1])
        {
            goThrough(map, new[] { x, y + 1 },visited); // north
            // ShowAtPosition(x, y)
        }
        if (x < map.GetLength(0) - 1 && map[x + 1, y] == 0 && !visited[x + 1, y])
        {
            goThrough(map, new[] { x + 1, y }, visited); // east
            // ShowAtPosition(x, y)
        }
        if (y < map.GetLength(1) - 1 && map[x, y + 1] == 0 && !visited[x, y + 1])
        {
            goThrough(map, new[] { x, y - 1 }, visited); // south
            // ShowAtPosition(x, y)
        }
        if (x > 0 && map[x - 1, y] == 0 && !visited[x - 1, y])
        {
            goThrough(map, new[] { x - 1, y }, visited); // west
            // ShowAtPosition(x, y)
        }
        if (NoZeros(visited)) { Console.WriteLine("I went through everything!"); Console.ReadLine(); }


    }

注意我写的WriteLine,所以我可以跟踪这个递归方法的每次迭代。 这是输出:

Position -> Column: 1 || Row: 31
Position -> Column: 2 || Row: 31
Position -> Column: 3 || Row: 31
Position -> Column: 4 || Row: 31
Position -> Column: 5 || Row: 31
Position -> Column: 6 || Row: 31
Position -> Column: 7 || Row: 31
Position -> Column: 8 || Row: 31
Position -> Column: 9 || Row: 31
Position -> Column: 10 || Row: 31
Position -> Column: 10 || Row: 32
Position -> Column: 11 || Row: 31
Position -> Column: 12 || Row: 31
Position -> Column: 13 || Row: 31
Position -> Column: 13 || Row: 32
Position -> Column: 14 || Row: 31
Position -> Column: 15 || Row: 31
Position -> Column: 16 || Row: 31
Position -> Column: 16 || Row: 32
Position -> Column: 17 || Row: 31
Position -> Column: 18 || Row: 31
Position -> Column: 19 || Row: 31
Position -> Column: 20 || Row: 31
Position -> Column: 21 || Row: 31
Position -> Column: 22 || Row: 31
Position -> Column: 23 || Row: 31
Position -> Column: 24 || Row: 31
Position -> Column: 25 || Row: 31
Position -> Column: 25 || Row: 30
Position -> Column: 1 || Row: 30

所以,首先,这种方法不能通过所有的迷宫,甚至不能关闭(是的,0都是连接的)。

其次,在最后一次迭代中(输出的最后两行),资源管理器从(25,30)“传送”到(1,30)。

顺便说一下,这是图像:

White =0's & Black =1's

2 个答案:

答案 0 :(得分:3)

起初听起来你只是在找maze solving algorithm;像左手墙的追随者。

但是,您不是在寻找迷宫中的路径,而是希望访问具有相同值的所有连续位置。基本上你可以使用flood fill algorithm

唯一的问题是你可能有多个0未连接的池(除非你的原始位图被构造成所有的0都连接起来,在这种情况下你可以确保所有的密钥只能将它们放在0个单元格上即可到达。因此,您可能需要从多个起点进行洪水填充,以确保所有内容都被覆盖。

答案 1 :(得分:1)

您可以创建一个包含您遇到的所有可能路径的树。每个节点代表地图中的某个点,所有子节点代表您可以访问的有效点。已访问的每个点都已标记,以便您不再尝试访问它。如果您随后执行深度优先树搜索,则可以四处走动,直到您探索了所有可能的位置。每当遇到受访节点时,您都​​不会再去那里。以下执行递归深度优先搜索。对于大型地图,您将需要一个非递归解决方案,否则您将获得StackOverflowException。

private bool[,] visited; // needs to have same size as map
public void GoThrough(int[,] map, int[] pos) {
  int x = pos[0];
  int y = pos[1];
  visited[x, y] = true;
  // ShowAtPosition(x, y)
  if (y > 0 && map[x, y - 1] == 0 && !visited[x, y - 1]) {
    GoThrough(map, new [] {x, y - 1}); // north
    // ShowAtPosition(x, y)
  }
  if (x < map.GetLength(0) - 1 && map[x + 1, y] == 0 && !visited[x + 1, y]) {
    GoThrough(map, new [] {x + 1, y}); // east
    // ShowAtPosition(x, y)
  }
  if (y < map.GetLength(1) - 1 && map[x, y + 1] == 0 && !visited[x, y + 1]) {
    GoThrough(map, new [] {x, y + 1}); // south
    // ShowAtPosition(x, y)
  }
  if (x > 0 && map[x - 1, y] == 0 && !visited[x - 1, y]) {
    GoThrough(map, new [] {x - 1, y}); // west
    // ShowAtPosition(x, y)
  }
}

它将遍历整个地图和所有可到达的图块,然后返回起点。

基本上,这是Matthew Strawbridge提到的洪水填充算法(当我输入答案时)。