C# - 停止内部递归(嵌套?)Foreach
C# - Stop recursion inside (nested?) Foreach
我正在尝试使用递归方法搜索特定类型的图块。问题是它变得无限。我认为这是因为它仍然在 foreach 的其余部分调用该方法,所以我想知道你们中是否有人有 improvement/correction。这是我正在使用的代码:
private Tiles LookForCheckedWlakable(Tiles t)
{
if (t.IsChecked())
return t;
else
{
foreach (Tiles n in t.neighbours)
{
if (!n.visited)
{
n.visited = true;
Tiles result = LookForCheckedWlakable(n);
if (result != null)
return result;
}
}
}
return null;
}
感谢您的宝贵时间。
编辑:
正如人们所问,这是我的 Tiles class(忽略 Monobehaviour,它是 Unity 的大师 class。另外,一些属性是 public 所以我可以窥探它们在 Unity 编辑器上。我会尽快将其改回私有):
public class Tiles : MonoBehaviour {
public List<Tiles> neighbours = new List<Tiles>();
public int x, y;
public Boolean isWalkable = false;
public Boolean check = false;
public Boolean visited = false;
/// <summary>
/// Allow other tiles to add themselves as a neighbour of their neighbours and vice versa. Fail if they already know each other.
/// </summary>
/// <param name="t">The tiles you want to add as a neighbour.</param>
public void addNeighbour(Tiles t)
{
if (!t.getNeighbour().Contains(this))
{
this.neighbours.Add(t);
t.getNeighbour().Add(this);
}
}
/// <summary>
/// Get the neighbours of this tiles
/// </summary>
/// <returns>A list with all of this tiles' neighbours</returns>
public List<Tiles> getNeighbour()
{
return this.neighbours;
}
}
感谢您指出由于访问未被重置,此代码只能使用一次,我将对此进行更改。
我不知道如何检查这是否是 "just being slow"。我已经有其他算法可以遍历我的地图,并且不会花费无限时间。
编辑 2:
我正在尝试用瓷砖制作 "game board"。它们可以是可步行的、障碍物或洞。我想随机生成它,但需要检查整个图是否仍然是连接的。我使用这种递归方法从一个孤立的瓦片中找到最近的可步行瓦片(我知道它是孤立的,因为我从一个起点开始填充我的图表,即时检查它们。当它们没有被检查时,它们是孤立的。)
大型编辑来解释我能想到的一切:
在这里,你可以看到我生成的图表。左边是我有的,右边是我想要的
(我想post直接图片,但显然我需要声望...)
可以看到"isolated one"。我想从孤立到 grpah 的其余部分。我知道图表的其余部分已被检查,多亏了这种方法(我从我手动检查的起始图块开始):
/// <summary>
/// Flood fill, aka check every walkable tiles from the starting tiles
/// </summary>
/// <param name="tiles">The starting tiles</param>
private void Floodfill(Tiles tiles)
{
//Create queue to flood fill
Queue<Tiles> queue = new Queue<Tiles>();
queue.Enqueue(tiles);
//We flood fill, aka we look for every components in the neighbours and check them.
//Any non checkes tiles is isolated.
while (queue.Count != 0)
{
Tiles t = queue.Dequeue();
t.CheckIt();
foreach (Tiles neighbour in t.neighbours)
{
if (neighbour.isWalkable && !neighbour.IsChecked())
queue.Enqueue(neighbour);
}
}
}
之后,我寻找隔离并执行此操作:
void TryConnexe()
{
//We found the spawn of the player on the left, which is a guaranteed walakable.
Tiles start = allTiles.Find(t => t.x == 1 && t.y == 9);
Floodfill(start);
//Now, we look in every of our tiles.
foreach (Tiles tiles in allTiles)
{
//As soon as it isn't checked, it's an isolated one.
if (tiles.isWalkable && !tiles.IsChecked())
{
//this is the line that makes everything goes infinite.
Tiles goal = LookForCheckedWlakable(tiles);
Debug.Log("recursivity ended with : ");
//we floodfill the remaining one, because we need to check them. Otherwise, the code will restart on a possible next tile.
Floodfill(tiles);
Dictionary<Tiles, Tiles> path = Pathfind(tiles, goal);
Tiles current = path[goal];
while (current != tiles)
{
current.isWalkable = true;
current.CheckIt();
current.GetComponentInChildren<SpriteRenderer>().color = Color.green;//walkable
goal = current;
}
}
}
}
我能想到的就这些了。如果您需要更多解释,请随时询问。
第 99 次看,在我看来,您只是误诊了故障点。我怀疑您的代码在 Tiles goal = LookForCheckedWlakable(tiles);
处并没有真正无限大,相反,它会在接下来的 while-loop
中无限大
while (current != tiles)
{
current.isWalkable = true;
current.CheckIt();
current.GetComponentInChildren<SpriteRenderer>().color = Color.green;//walkable
goal = current; // bad
}
我的 crystal 球告诉我,你可以通过更正你的循环来解决它 "increment":
while (current != tiles)
{
current.isWalkable = true;
current.CheckIt();
current.GetComponentInChildren<SpriteRenderer>().color = Color.green;//walkable
current = path[current]; // better, depending on the actual result of Pathfind
}
如果我的 crystal 球错了,请继续我原来的答案并开始寻找你的不同之处。
请参阅下面我的长答案,我在其中深入测试了您的 LookForCheckedWlakable
只是为了发现:它可能没有错。
好的,我尽我所知重现了您的磁贴配置并尝试重现您的问题(variable/function 名称只有一些细微差别)。
结果:代码为运行,没有出现死循环。请随意测试我的代码并将其用作参考,以了解您在实际代码中做错了什么。
据我所知,您遗漏了问题的一些关键细节,因为您不知道自己遗漏了什么,所以我写下这个答案是为了让您有一个起点。
public class Tiles
{
public int X { get; set; }
public int Y { get; set; }
public bool IsChecked { get; set; }
public bool IsWalkable { get; set; }
public bool Visited { get; set; }
private List<Tiles> _neighbours = new List<Tiles>();
public IEnumerable<Tiles> GetNeighbours()
{
return _neighbours;
}
public void AddNeighbour(Tiles neighbour)
{
if (!_neighbours.Contains(neighbour))
{
_neighbours.Add(neighbour);
neighbour._neighbours.Add(this);
}
}
}
public static class TileSolver
{
// just run this to emulate your example
public static void RunExample()
{
var t1 = GenerateTilePositions();
var t2 = GenerateTiles(t1);
var start = t2.First(x => x.X == 0 && x.Y == 8);
Floodfill(start);
//Now, we look in every of our tiles.
foreach (Tiles tile in t2)
{
//As soon as it isn't checked, it's an isolated one.
if (tile.IsWalkable && !tile.IsChecked)
{
//this is the line that makes everything goes infinite.
Tiles goal = LookForCheckedWlakable(tile);
//we floodfill the remaining one, because we need to check them. Otherwise, the code will restart on a possible next tile.
Floodfill(tile);
// no need to for the rest, since you claim LookForCheckedWlakable is at fault
// and you don't provide code for Pathfind and GetComponentInChildren
}
}
}
private static Tiles LookForCheckedWlakable(Tiles t)
{
if (t.IsChecked)
return t;
else
{
foreach (Tiles n in t.GetNeighbours())
{
if (!n.Visited)
{
n.Visited = true;
Tiles result = LookForCheckedWlakable(n);
if (result != null)
return result;
}
}
}
return null;
}
private static void Floodfill(Tiles tiles)
{
//Create queue to flood fill
Queue<Tiles> queue = new Queue<Tiles>();
queue.Enqueue(tiles);
//We flood fill, aka we look for every components in the neighbours and check them.
//Any non checkes tiles is isolated.
while (queue.Count != 0)
{
Tiles t = queue.Dequeue();
t.IsChecked = true;
foreach (Tiles neighbour in t.GetNeighbours())
{
if (neighbour.IsWalkable && !neighbour.IsChecked)
queue.Enqueue(neighbour);
}
}
}
/// <summary>
/// generate a hexagon of tile positions for the following indexing pattern:
/// Suppose a triangle with the points: upper left, upper right, bottom center
/// The parameter N describes the count of Tiles on the edges of the generated hexagon.
/// The relation of triangle and hexagon is as follows:
///
/// (N - 1, 0) (2N - 2, 0)
/// (0, 0) . . x x x . . (3N - 3, 0)
/// . x x x x .
/// (0, N - 1) x x x x x (2N - 2, N - 1)
/// x x x x
/// (0, 2N - 2) x x x (N - 1, 2N - 2)
/// . .
/// .
/// (0, 3N - 3)
///
/// The indices start at (x=0, y=0) upper left of the triangle, increasing x while going to the right
/// and increasing y while going down and half-right.
/// </summary>
/// <param name="N"></param>
/// <returns></returns>
private static List<Tuple<int, int>> GenerateTilePositions()
{
int N = 9;
var result = new List<Tuple<int, int>>();
for (int x = 0; x < 3 * N - 2; x++)
{
for (int y = 0; y < 3 * N - 2; y++)
{
if (N - 2 < x + y &&
x + y < 3 * N - 2 &&
x < 2 * N - 1 &&
y < 2 * N - 1)
{
result.Add(new Tuple<int, int>(x, y));
}
}
}
return result;
}
private static void SetNotWalkable(Dictionary<Tuple<int, int>, Tiles> tilesDict, int x, int y)
{
tilesDict[Tuple.Create(x, y)].IsWalkable = false;
}
private static void TryAddNeighbour(Dictionary<Tuple<int, int>, Tiles> tilesDict, Tiles item, int offsetX, int offsetY)
{
Tiles neighbour;
if (tilesDict.TryGetValue(Tuple.Create(item.X + offsetX, item.Y + offsetY), out neighbour))
{
item.AddNeighbour(neighbour);
}
}
private static List<Tiles> GenerateTiles(List<Tuple<int, int>> t2)
{
var tilesDict = t2.ToDictionary(
pos => pos,
pos => new Tiles
{
X = pos.Item1,
Y = pos.Item2,
IsChecked = false,
Visited = false,
IsWalkable = true, // some will be changed manually
});
// connect neighbours
foreach (var item in tilesDict.Values)
{
TryAddNeighbour(tilesDict, item, -1, 0);
TryAddNeighbour(tilesDict, item, 1, 0);
TryAddNeighbour(tilesDict, item, 0, -1);
TryAddNeighbour(tilesDict, item, 0, 1);
TryAddNeighbour(tilesDict, item, -1, 1);
TryAddNeighbour(tilesDict, item, 1, -1);
}
// Unchecked Green positions after FloodFill:
//Tuple.Create(8, 0);
//Tuple.Create(7, 1);
//Tuple.Create(7, 2);
// Special positions (red, black)
SetNotWalkable(tilesDict, 9, 0);
SetNotWalkable(tilesDict, 14, 0);
SetNotWalkable(tilesDict, 15, 0);
SetNotWalkable(tilesDict, 16, 0);
SetNotWalkable(tilesDict, 8, 1);
SetNotWalkable(tilesDict, 11, 1);
SetNotWalkable(tilesDict, 12, 1);
SetNotWalkable(tilesDict, 6, 2);
SetNotWalkable(tilesDict, 8, 2);
SetNotWalkable(tilesDict, 12, 2);
SetNotWalkable(tilesDict, 14, 2);
SetNotWalkable(tilesDict, 6, 3);
SetNotWalkable(tilesDict, 7, 3);
SetNotWalkable(tilesDict, 10, 3);
SetNotWalkable(tilesDict, 13, 3);
SetNotWalkable(tilesDict, 10, 4);
SetNotWalkable(tilesDict, 12, 4);
SetNotWalkable(tilesDict, 13, 4);
SetNotWalkable(tilesDict, 14, 4);
SetNotWalkable(tilesDict, 3, 5);
SetNotWalkable(tilesDict, 6, 5);
SetNotWalkable(tilesDict, 8, 5);
SetNotWalkable(tilesDict, 9, 5);
SetNotWalkable(tilesDict, 12, 5);
SetNotWalkable(tilesDict, 15, 5);
SetNotWalkable(tilesDict, 2, 6);
SetNotWalkable(tilesDict, 3, 6);
SetNotWalkable(tilesDict, 7, 6);
SetNotWalkable(tilesDict, 9, 6);
SetNotWalkable(tilesDict, 16, 6);
SetNotWalkable(tilesDict, 1, 7);
SetNotWalkable(tilesDict, 3, 7);
SetNotWalkable(tilesDict, 7, 7);
SetNotWalkable(tilesDict, 9, 7);
SetNotWalkable(tilesDict, 12, 7);
SetNotWalkable(tilesDict, 16, 7);
SetNotWalkable(tilesDict, 9, 8);
SetNotWalkable(tilesDict, 12, 8);
SetNotWalkable(tilesDict, 13, 8);
SetNotWalkable(tilesDict, 0, 9);
SetNotWalkable(tilesDict, 1, 9);
SetNotWalkable(tilesDict, 6, 9);
SetNotWalkable(tilesDict, 7, 9);
SetNotWalkable(tilesDict, 8, 9);
SetNotWalkable(tilesDict, 10, 9);
SetNotWalkable(tilesDict, 12, 9);
SetNotWalkable(tilesDict, 13, 9);
SetNotWalkable(tilesDict, 3, 10);
SetNotWalkable(tilesDict, 4, 10);
SetNotWalkable(tilesDict, 8, 10);
SetNotWalkable(tilesDict, 10, 10);
SetNotWalkable(tilesDict, 5, 11);
SetNotWalkable(tilesDict, 6, 11);
SetNotWalkable(tilesDict, 9, 11);
SetNotWalkable(tilesDict, 10, 11);
SetNotWalkable(tilesDict, 4, 12);
SetNotWalkable(tilesDict, 6, 12);
SetNotWalkable(tilesDict, 9, 12);
SetNotWalkable(tilesDict, 11, 12);
SetNotWalkable(tilesDict, 6, 13);
SetNotWalkable(tilesDict, 7, 13);
SetNotWalkable(tilesDict, 9, 13);
SetNotWalkable(tilesDict, 11, 13);
SetNotWalkable(tilesDict, 0, 14);
SetNotWalkable(tilesDict, 2, 14);
SetNotWalkable(tilesDict, 3, 14);
SetNotWalkable(tilesDict, 8, 14);
SetNotWalkable(tilesDict, 9, 14);
SetNotWalkable(tilesDict, 0, 15);
SetNotWalkable(tilesDict, 7, 15);
SetNotWalkable(tilesDict, 0, 16);
SetNotWalkable(tilesDict, 2, 16);
SetNotWalkable(tilesDict, 3, 16);
SetNotWalkable(tilesDict, 4, 16);
SetNotWalkable(tilesDict, 5, 16);
SetNotWalkable(tilesDict, 7, 16);
return tilesDict.Values.ToList();
}
}
我正在尝试使用递归方法搜索特定类型的图块。问题是它变得无限。我认为这是因为它仍然在 foreach 的其余部分调用该方法,所以我想知道你们中是否有人有 improvement/correction。这是我正在使用的代码:
private Tiles LookForCheckedWlakable(Tiles t)
{
if (t.IsChecked())
return t;
else
{
foreach (Tiles n in t.neighbours)
{
if (!n.visited)
{
n.visited = true;
Tiles result = LookForCheckedWlakable(n);
if (result != null)
return result;
}
}
}
return null;
}
感谢您的宝贵时间。
编辑:
正如人们所问,这是我的 Tiles class(忽略 Monobehaviour,它是 Unity 的大师 class。另外,一些属性是 public 所以我可以窥探它们在 Unity 编辑器上。我会尽快将其改回私有):
public class Tiles : MonoBehaviour {
public List<Tiles> neighbours = new List<Tiles>();
public int x, y;
public Boolean isWalkable = false;
public Boolean check = false;
public Boolean visited = false;
/// <summary>
/// Allow other tiles to add themselves as a neighbour of their neighbours and vice versa. Fail if they already know each other.
/// </summary>
/// <param name="t">The tiles you want to add as a neighbour.</param>
public void addNeighbour(Tiles t)
{
if (!t.getNeighbour().Contains(this))
{
this.neighbours.Add(t);
t.getNeighbour().Add(this);
}
}
/// <summary>
/// Get the neighbours of this tiles
/// </summary>
/// <returns>A list with all of this tiles' neighbours</returns>
public List<Tiles> getNeighbour()
{
return this.neighbours;
}
}
感谢您指出由于访问未被重置,此代码只能使用一次,我将对此进行更改。 我不知道如何检查这是否是 "just being slow"。我已经有其他算法可以遍历我的地图,并且不会花费无限时间。
编辑 2:
我正在尝试用瓷砖制作 "game board"。它们可以是可步行的、障碍物或洞。我想随机生成它,但需要检查整个图是否仍然是连接的。我使用这种递归方法从一个孤立的瓦片中找到最近的可步行瓦片(我知道它是孤立的,因为我从一个起点开始填充我的图表,即时检查它们。当它们没有被检查时,它们是孤立的。)
大型编辑来解释我能想到的一切:
在这里,你可以看到我生成的图表。左边是我有的,右边是我想要的
(我想post直接图片,但显然我需要声望...)
可以看到"isolated one"。我想从孤立到 grpah 的其余部分。我知道图表的其余部分已被检查,多亏了这种方法(我从我手动检查的起始图块开始):
/// <summary>
/// Flood fill, aka check every walkable tiles from the starting tiles
/// </summary>
/// <param name="tiles">The starting tiles</param>
private void Floodfill(Tiles tiles)
{
//Create queue to flood fill
Queue<Tiles> queue = new Queue<Tiles>();
queue.Enqueue(tiles);
//We flood fill, aka we look for every components in the neighbours and check them.
//Any non checkes tiles is isolated.
while (queue.Count != 0)
{
Tiles t = queue.Dequeue();
t.CheckIt();
foreach (Tiles neighbour in t.neighbours)
{
if (neighbour.isWalkable && !neighbour.IsChecked())
queue.Enqueue(neighbour);
}
}
}
之后,我寻找隔离并执行此操作:
void TryConnexe()
{
//We found the spawn of the player on the left, which is a guaranteed walakable.
Tiles start = allTiles.Find(t => t.x == 1 && t.y == 9);
Floodfill(start);
//Now, we look in every of our tiles.
foreach (Tiles tiles in allTiles)
{
//As soon as it isn't checked, it's an isolated one.
if (tiles.isWalkable && !tiles.IsChecked())
{
//this is the line that makes everything goes infinite.
Tiles goal = LookForCheckedWlakable(tiles);
Debug.Log("recursivity ended with : ");
//we floodfill the remaining one, because we need to check them. Otherwise, the code will restart on a possible next tile.
Floodfill(tiles);
Dictionary<Tiles, Tiles> path = Pathfind(tiles, goal);
Tiles current = path[goal];
while (current != tiles)
{
current.isWalkable = true;
current.CheckIt();
current.GetComponentInChildren<SpriteRenderer>().color = Color.green;//walkable
goal = current;
}
}
}
}
我能想到的就这些了。如果您需要更多解释,请随时询问。
第 99 次看,在我看来,您只是误诊了故障点。我怀疑您的代码在 Tiles goal = LookForCheckedWlakable(tiles);
处并没有真正无限大,相反,它会在接下来的 while-loop
while (current != tiles)
{
current.isWalkable = true;
current.CheckIt();
current.GetComponentInChildren<SpriteRenderer>().color = Color.green;//walkable
goal = current; // bad
}
我的 crystal 球告诉我,你可以通过更正你的循环来解决它 "increment":
while (current != tiles)
{
current.isWalkable = true;
current.CheckIt();
current.GetComponentInChildren<SpriteRenderer>().color = Color.green;//walkable
current = path[current]; // better, depending on the actual result of Pathfind
}
如果我的 crystal 球错了,请继续我原来的答案并开始寻找你的不同之处。
请参阅下面我的长答案,我在其中深入测试了您的 LookForCheckedWlakable
只是为了发现:它可能没有错。
好的,我尽我所知重现了您的磁贴配置并尝试重现您的问题(variable/function 名称只有一些细微差别)。
结果:代码为运行,没有出现死循环。请随意测试我的代码并将其用作参考,以了解您在实际代码中做错了什么。
据我所知,您遗漏了问题的一些关键细节,因为您不知道自己遗漏了什么,所以我写下这个答案是为了让您有一个起点。
public class Tiles
{
public int X { get; set; }
public int Y { get; set; }
public bool IsChecked { get; set; }
public bool IsWalkable { get; set; }
public bool Visited { get; set; }
private List<Tiles> _neighbours = new List<Tiles>();
public IEnumerable<Tiles> GetNeighbours()
{
return _neighbours;
}
public void AddNeighbour(Tiles neighbour)
{
if (!_neighbours.Contains(neighbour))
{
_neighbours.Add(neighbour);
neighbour._neighbours.Add(this);
}
}
}
public static class TileSolver
{
// just run this to emulate your example
public static void RunExample()
{
var t1 = GenerateTilePositions();
var t2 = GenerateTiles(t1);
var start = t2.First(x => x.X == 0 && x.Y == 8);
Floodfill(start);
//Now, we look in every of our tiles.
foreach (Tiles tile in t2)
{
//As soon as it isn't checked, it's an isolated one.
if (tile.IsWalkable && !tile.IsChecked)
{
//this is the line that makes everything goes infinite.
Tiles goal = LookForCheckedWlakable(tile);
//we floodfill the remaining one, because we need to check them. Otherwise, the code will restart on a possible next tile.
Floodfill(tile);
// no need to for the rest, since you claim LookForCheckedWlakable is at fault
// and you don't provide code for Pathfind and GetComponentInChildren
}
}
}
private static Tiles LookForCheckedWlakable(Tiles t)
{
if (t.IsChecked)
return t;
else
{
foreach (Tiles n in t.GetNeighbours())
{
if (!n.Visited)
{
n.Visited = true;
Tiles result = LookForCheckedWlakable(n);
if (result != null)
return result;
}
}
}
return null;
}
private static void Floodfill(Tiles tiles)
{
//Create queue to flood fill
Queue<Tiles> queue = new Queue<Tiles>();
queue.Enqueue(tiles);
//We flood fill, aka we look for every components in the neighbours and check them.
//Any non checkes tiles is isolated.
while (queue.Count != 0)
{
Tiles t = queue.Dequeue();
t.IsChecked = true;
foreach (Tiles neighbour in t.GetNeighbours())
{
if (neighbour.IsWalkable && !neighbour.IsChecked)
queue.Enqueue(neighbour);
}
}
}
/// <summary>
/// generate a hexagon of tile positions for the following indexing pattern:
/// Suppose a triangle with the points: upper left, upper right, bottom center
/// The parameter N describes the count of Tiles on the edges of the generated hexagon.
/// The relation of triangle and hexagon is as follows:
///
/// (N - 1, 0) (2N - 2, 0)
/// (0, 0) . . x x x . . (3N - 3, 0)
/// . x x x x .
/// (0, N - 1) x x x x x (2N - 2, N - 1)
/// x x x x
/// (0, 2N - 2) x x x (N - 1, 2N - 2)
/// . .
/// .
/// (0, 3N - 3)
///
/// The indices start at (x=0, y=0) upper left of the triangle, increasing x while going to the right
/// and increasing y while going down and half-right.
/// </summary>
/// <param name="N"></param>
/// <returns></returns>
private static List<Tuple<int, int>> GenerateTilePositions()
{
int N = 9;
var result = new List<Tuple<int, int>>();
for (int x = 0; x < 3 * N - 2; x++)
{
for (int y = 0; y < 3 * N - 2; y++)
{
if (N - 2 < x + y &&
x + y < 3 * N - 2 &&
x < 2 * N - 1 &&
y < 2 * N - 1)
{
result.Add(new Tuple<int, int>(x, y));
}
}
}
return result;
}
private static void SetNotWalkable(Dictionary<Tuple<int, int>, Tiles> tilesDict, int x, int y)
{
tilesDict[Tuple.Create(x, y)].IsWalkable = false;
}
private static void TryAddNeighbour(Dictionary<Tuple<int, int>, Tiles> tilesDict, Tiles item, int offsetX, int offsetY)
{
Tiles neighbour;
if (tilesDict.TryGetValue(Tuple.Create(item.X + offsetX, item.Y + offsetY), out neighbour))
{
item.AddNeighbour(neighbour);
}
}
private static List<Tiles> GenerateTiles(List<Tuple<int, int>> t2)
{
var tilesDict = t2.ToDictionary(
pos => pos,
pos => new Tiles
{
X = pos.Item1,
Y = pos.Item2,
IsChecked = false,
Visited = false,
IsWalkable = true, // some will be changed manually
});
// connect neighbours
foreach (var item in tilesDict.Values)
{
TryAddNeighbour(tilesDict, item, -1, 0);
TryAddNeighbour(tilesDict, item, 1, 0);
TryAddNeighbour(tilesDict, item, 0, -1);
TryAddNeighbour(tilesDict, item, 0, 1);
TryAddNeighbour(tilesDict, item, -1, 1);
TryAddNeighbour(tilesDict, item, 1, -1);
}
// Unchecked Green positions after FloodFill:
//Tuple.Create(8, 0);
//Tuple.Create(7, 1);
//Tuple.Create(7, 2);
// Special positions (red, black)
SetNotWalkable(tilesDict, 9, 0);
SetNotWalkable(tilesDict, 14, 0);
SetNotWalkable(tilesDict, 15, 0);
SetNotWalkable(tilesDict, 16, 0);
SetNotWalkable(tilesDict, 8, 1);
SetNotWalkable(tilesDict, 11, 1);
SetNotWalkable(tilesDict, 12, 1);
SetNotWalkable(tilesDict, 6, 2);
SetNotWalkable(tilesDict, 8, 2);
SetNotWalkable(tilesDict, 12, 2);
SetNotWalkable(tilesDict, 14, 2);
SetNotWalkable(tilesDict, 6, 3);
SetNotWalkable(tilesDict, 7, 3);
SetNotWalkable(tilesDict, 10, 3);
SetNotWalkable(tilesDict, 13, 3);
SetNotWalkable(tilesDict, 10, 4);
SetNotWalkable(tilesDict, 12, 4);
SetNotWalkable(tilesDict, 13, 4);
SetNotWalkable(tilesDict, 14, 4);
SetNotWalkable(tilesDict, 3, 5);
SetNotWalkable(tilesDict, 6, 5);
SetNotWalkable(tilesDict, 8, 5);
SetNotWalkable(tilesDict, 9, 5);
SetNotWalkable(tilesDict, 12, 5);
SetNotWalkable(tilesDict, 15, 5);
SetNotWalkable(tilesDict, 2, 6);
SetNotWalkable(tilesDict, 3, 6);
SetNotWalkable(tilesDict, 7, 6);
SetNotWalkable(tilesDict, 9, 6);
SetNotWalkable(tilesDict, 16, 6);
SetNotWalkable(tilesDict, 1, 7);
SetNotWalkable(tilesDict, 3, 7);
SetNotWalkable(tilesDict, 7, 7);
SetNotWalkable(tilesDict, 9, 7);
SetNotWalkable(tilesDict, 12, 7);
SetNotWalkable(tilesDict, 16, 7);
SetNotWalkable(tilesDict, 9, 8);
SetNotWalkable(tilesDict, 12, 8);
SetNotWalkable(tilesDict, 13, 8);
SetNotWalkable(tilesDict, 0, 9);
SetNotWalkable(tilesDict, 1, 9);
SetNotWalkable(tilesDict, 6, 9);
SetNotWalkable(tilesDict, 7, 9);
SetNotWalkable(tilesDict, 8, 9);
SetNotWalkable(tilesDict, 10, 9);
SetNotWalkable(tilesDict, 12, 9);
SetNotWalkable(tilesDict, 13, 9);
SetNotWalkable(tilesDict, 3, 10);
SetNotWalkable(tilesDict, 4, 10);
SetNotWalkable(tilesDict, 8, 10);
SetNotWalkable(tilesDict, 10, 10);
SetNotWalkable(tilesDict, 5, 11);
SetNotWalkable(tilesDict, 6, 11);
SetNotWalkable(tilesDict, 9, 11);
SetNotWalkable(tilesDict, 10, 11);
SetNotWalkable(tilesDict, 4, 12);
SetNotWalkable(tilesDict, 6, 12);
SetNotWalkable(tilesDict, 9, 12);
SetNotWalkable(tilesDict, 11, 12);
SetNotWalkable(tilesDict, 6, 13);
SetNotWalkable(tilesDict, 7, 13);
SetNotWalkable(tilesDict, 9, 13);
SetNotWalkable(tilesDict, 11, 13);
SetNotWalkable(tilesDict, 0, 14);
SetNotWalkable(tilesDict, 2, 14);
SetNotWalkable(tilesDict, 3, 14);
SetNotWalkable(tilesDict, 8, 14);
SetNotWalkable(tilesDict, 9, 14);
SetNotWalkable(tilesDict, 0, 15);
SetNotWalkable(tilesDict, 7, 15);
SetNotWalkable(tilesDict, 0, 16);
SetNotWalkable(tilesDict, 2, 16);
SetNotWalkable(tilesDict, 3, 16);
SetNotWalkable(tilesDict, 4, 16);
SetNotWalkable(tilesDict, 5, 16);
SetNotWalkable(tilesDict, 7, 16);
return tilesDict.Values.ToList();
}
}