[英]Algorithm to find map regions in c#
我想給這些區域編號。我在下面分享我缺少的算法。
int i = 1;
for (int x= 0; x< height ; x++)
{
for (int y= 0; y< width ; y++)
{
if (y>= 1)
{
if (a[x- 1, ] != "0")
{
if(a[x, y]!="0")
{
a[x, y] = a[x- 1, y];
}
}
else
{
if(a[x, y] != "0")
{
a[x, y] = "?";
}
}
}
else
{
if (a[x, y] != "0")
{
a[x, y] = i.ToString();
}
else
{
if (x>= 1)
{
if (a[x, y- 1] != a[x, y])
i++;
}
}
}
Console.Write(string.Format("{0} ", a[x, y]));
}
Console.Write(Environment.NewLine);
}
您對更有效的算法有什么建議或任何想法如何改進此算法。謝謝您的幫助。
一個簡單但有效的幼稚實現是這樣做:
這是一個簡單的實現。 請注意,我使用int?[,]
矩形數組來保存 map,您必須根據需要調整代碼。 I use LINQPad to test this in, so the .Dump()
extension method there simply dumps the output of the LINQ query to the output window. 示例 output 下面的代碼:
void Main()
{
var map = new int?[30, 20];
for (int x = 0; x < 30; x++)
{
map[x, 10 - x / 3] = 0;
map[x, 5 + x / 2] = 0;
map[x, 18 - x / 5] = 0;
}
ShowMap(map);
NumberRegions(map);
ShowMap(map);
}
public static void ShowMap(int?[,] map)
{
Enumerable.Range(0, map.GetLength(1))
.Select(y => string.Join("", Enumerable.Range(0, map.GetLength(0)).Select(x => map[x, y]?.ToString() ?? "?")))
.Dump();
}
public static void NumberRegions(int?[,] map)
{
var stack = new Stack<(int x, int y)>();
int nextNumber = 1;
for (int x = 0; x < map.GetLength(0); x++)
{
for (int y = 0; y < map.GetLength(1); y++)
{
if (map[x, y] is null)
{
stack.Push((x, y));
while (stack.Any())
{
(int cx, int cy) = stack.Pop();
if (map[cx, cy] is null)
{
map[cx, cy] = nextNumber;
if (cx > 0) stack.Push((cx - 1, cy));
if (cx < map.GetLength(0) - 1) stack.Push((cx + 1, cy));
if (cy > 0) stack.Push((cx, cy - 1));
if (cy < map.GetLength(1) - 1) stack.Push((cx, cy + 1));
}
}
nextNumber++;
}
}
}
}
這是示例 output:
Before:
??????????????????????????????
???????????????????????????000
????????????????????????000???
?????????????????????000??????
??????????????????000?????????
00?????????????000????????????
??00????????000???????????????
????00???000??????????????????
??????000?????????????????????
???000??00????????????????????
000???????00??????????????????
????????????00????????????????
??????????????00??????????????
????????????????00???????00000
??????????????????0000000?????
???????????????0000000????????
??????????00000???????00??????
?????00000??????????????00????
00000?????????????????????00??
????????????????????????????00
After:
111111111111111111111111111111
111111111111111111111111111000
111111111111111111111111000555
111111111111111111111000555555
111111111111111111000555555555
001111111111111000555555555555
220011111111000555555555555555
222200111000555555555555555555
222222000555555555555555555555
222000330055555555555555555555
000333333300555555555555555555
333333333333005555555555555555
333333333333330055555555555555
333333333333333300555555500000
333333333333333333000000066666
333333333333333000000066666666
333333333300000444444400666666
333330000044444444444444006666
000004444444444444444444440066
444444444444444444444444444400
我說這是一個幼稚的實現的原因是,如果你有一個非常大的 map,“搜索下一個未編號的單元格”可能很重要。 如果你能找到一個好方法來跟蹤你發現的 0 邊界,以便你可以在這些邊界周圍尋找未編號的單元格,那可能會奏效,但這里有很多邊緣情況需要考慮,所以我什至沒有打擾試。
這是一個變體,它簡單地將洪水填充實現拆分為一個單獨的方法:
public static void NumberRegions(int?[,] map)
{
int nextNumber = 1;
for (int x = 0; x < map.GetLength(0); x++)
for (int y = 0; y < map.GetLength(1); y++)
if (map[x, y] is null)
{
FloodFill(map, x, y, nextNumber);
nextNumber++;
}
}
public static void FloodFill(int?[,] map, int x, int y, int number)
{
var work = new Stack<(int x, int y)>();
work.Push((x, y));
while (work.Any())
{
(x, y) = work.Pop();
if (map[x, y] is not null)
continue;
map[x, y] = number;
if (x > 0) work.Push((x - 1, y));
if (x < map.GetLength(0) - 1) work.Push((x + 1, y));
if (y > 0) work.Push((x, y - 1));
if (y < map.GetLength(1) - 1) work.Push((x, y + 1));
}
}
由於您在評論中提到了一些要求,如果您不能使用Stack<>
類型,這里是上面 FloodFill 方法的遞歸版本:
public static void FloodFill(int?[,] map, int x, int y, int number)
{
if (map[x, y] is null)
{
map[x, y] = number;
if (x > 0) FloodFill(map, x-1, y, number);
if (x < map.GetLength(0) - 1) FloodFill(map, x+1, y, number);
if (y > 0) FloodFill(map, x, y-1, number);
if (y < map.GetLength(1) - 1) FloodFill(map, x, y+1, number);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.