C# - 递归函数问题
这是我的功能:
static Map AddFormation(Map _map, Tile tile, int x, int y, int length,
Random rand, Tile endTile = (Tile)Int32.MaxValue)
{
//so a call to AddFormation without the endTile will work, if I don't want a border.
if ((int)endTile == Int32.MaxValue) endTile = tile;
if (x >= 0 && x < _map.Data.GetLength(0) && y >= 0 && y < _map.Data.GetLength(1))
{
if (_map.Data[x, y].Tile != tile)
{
if (length > 0)
{
_map.Data[x, y].Tile = tile;
int newlength = length - 1;
AddFormation(_map, tile, x, y - 1, newlength, rand, endTile); // ^
AddFormation(_map, tile, x, y + 1, newlength, rand, endTile); // v
AddFormation(_map, tile, x - 1, y, newlength, rand, endTile); // <-
AddFormation(_map, tile, x + 1, y, newlength, rand, endTile); // ->
}
else
{
_map.Data[x, y].Tile = endTile;
}
}
}
return _map;
}
我有一个 Tile 枚举,它可以让我在使用 Tile 时变得更轻松。 我有一个 Cell 类,其中包含一个名为“Tile”的 Tile 枚举和其他信息(对此不重要) Map 类包含一个称为 Data 的 Cell[,] 组。
我想要实现的是在特定点创建特定图块的块,稍后我将把随机化纳入其中(这样它就不仅仅是一颗钻石),但我把它拿出来看看这是否是原因我的问题。
问题是对该函数的调用总是产生比宽度高的块,我一生都无法明白为什么。
会发生什么:
public static int[,] Add(int[,] grid, int x, int y, int length, int value)
{
if (x >= 0 && y >= 0 && x < grid.GetLength(0) && y < grid.GetLength(1))
{
if(grid[x,y] != value)
{
if(length > 0)
{
grid[x, y] = value;
Add(grid, x - 1, y, length - 1, value);
Add(grid, x + 1, y, length - 1, value);
Add(grid, x, y - 1, length - 1, value);
Add(grid, x, y + 1, length - 1, value);
}
}
}
return grid;
}
我创建了一个测试函数来看看如果我使用类似的东西 如果你的尺寸足够大,也会出现同样的问题(5 会产生完美的钻石,6 会产生奇怪的形状,11 会产生更奇怪的形状)
Here's my function:
static Map AddFormation(Map _map, Tile tile, int x, int y, int length,
Random rand, Tile endTile = (Tile)Int32.MaxValue)
{
//so a call to AddFormation without the endTile will work, if I don't want a border.
if ((int)endTile == Int32.MaxValue) endTile = tile;
if (x >= 0 && x < _map.Data.GetLength(0) && y >= 0 && y < _map.Data.GetLength(1))
{
if (_map.Data[x, y].Tile != tile)
{
if (length > 0)
{
_map.Data[x, y].Tile = tile;
int newlength = length - 1;
AddFormation(_map, tile, x, y - 1, newlength, rand, endTile); // ^
AddFormation(_map, tile, x, y + 1, newlength, rand, endTile); // v
AddFormation(_map, tile, x - 1, y, newlength, rand, endTile); // <-
AddFormation(_map, tile, x + 1, y, newlength, rand, endTile); // ->
}
else
{
_map.Data[x, y].Tile = endTile;
}
}
}
return _map;
}
I have a Tile enum which is to make my life easier when working with the tiles.
I have a Cell class which contains a Tile enum called "Tile" and other info (unimportant to this)
The Map class contains a Cell[,] group called Data.
What I am trying to achieve is to create a block of the specific tile at a specific point, I will later incorporate Randomisation into this (so it wouldn't be just a diamond) but I took it out to see if that was the cause of my issue.
The problem is a call to this function always produces blocks taller than they are wide and I can't for the life of me see why..
I created a test function to see what happens if I use something like:
public static int[,] Add(int[,] grid, int x, int y, int length, int value)
{
if (x >= 0 && y >= 0 && x < grid.GetLength(0) && y < grid.GetLength(1))
{
if(grid[x,y] != value)
{
if(length > 0)
{
grid[x, y] = value;
Add(grid, x - 1, y, length - 1, value);
Add(grid, x + 1, y, length - 1, value);
Add(grid, x, y - 1, length - 1, value);
Add(grid, x, y + 1, length - 1, value);
}
}
}
return grid;
}
Which seems to suffer from the same problem if you go big enough (5 produces a perfect diamond, 6 produces a strange shape and something like 11 even stranger)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
好吧,在花了很长时间之后(我确实喜欢递归),这里是解决方案的一部分(可能很难解释):
问题是你允许“路径”沿着已经存在的单元格回溯被分配为
endTile
。如果您看一下第一个方法,您会发现搜索点在向上搜索后直接向下移动。您只需将其删除即可。这是我正在使用的代码(请注意,它调用
AddFormationAlt
两次,一次用于上升,一次用于下降):我更改了所有
Data[x, y]
到Data[y, x]
因为这就是我通常存储它们的方式,然后它就起作用了 xD。在
aleft
和aright
中,您想要的菱形的左半部分和右半部分位于单独的Map
中,您需要将它们连接在一起不知何故(对于像你这样聪明的人来说应该不会太难:)。left
和right
显示Map
的文本表示(注意中心的重叠):left
:< code>right:
您需要清理它并将所有类更改回您自己的类。我希望这有帮助!
Ok, after spending a long time on this (I do like recursion), here is partway to the solution (it may be hard to explain):
The problem is that you are allowing the "path" to backtrack along the cells that have already been allocated as
endTile
s. If you take a look at your first method, you make the search point go down straight after it has searched up. You simply need to remove that.This is the code I am using (notice that it calls
AddFormationAlt
twice, once for going up, once for going down):I changed all your
Data[x, y]
toData[y, x]
because that's how I usually store them and then it worked xD.In
aleft
andaright
you have the left half and the right half of the diamond you want in separateMap
s, you need to join them together somehow (shouldn't be too hard for a clever guy like you :).left
andright
show the textual representation ofMap
s (note the overlap in the centre):left
:right
:You need to clean this up and change all the classes back to your own ones. I hope this helps!
当你说:
如果你没有遇到任何已经设置为该值的块,你就告诉它只继续沿着这条“腿”走。问题是,一旦获得足够长的长度,从起点顶部伸出的“腿”就会向左和向右“螺旋”,因此当递归最终回到它开始尝试的点时向左或向右出去,那里已经有一个广场,你立即返回。
看起来您想要将
if(length > 0)
放在if(grid[x,y] != value)之后 /code> 块,而不是其内部。这样,您只需“设置”尚未设置的值,但您将继续,直到达到适当的长度。
当然,由于“分支”(即
if
语句)比“赋值”(即在数组中设置值)需要更长的时间,因此您不妨删除if(grid[x ,y] != value)
完全如此,并且有多次将点设置为相同值的风险,因为它比比较当前值更便宜。When you say:
You're telling it to only continue down this "leg" if you don't run into any blocks that have already been set to this value. The problem is that once you get a long enough length, the "leg" going out the top of the starting point "spirals around" to the left and right, and so when the recursion finally comes back to the point where it starts trying to go out the left or right, there is already a square there and you return immediately.
It looks like you want to take the
if(length > 0)
and put it after theif(grid[x,y] != value)
block, rather than inside of it. That way, you only "set" the value if it hasn't already been set, but you will continue until you reach the appropriate length.Of course, since "branches" (i.e.
if
statements) take longer than "assignments" (i.e. setting a value in an array), you might as well just remove theif(grid[x,y] != value)
entirely, and risk setting spots to the same value multiple times, because it's cheaper than comparing the current value.难道你不想要类似的东西吗
?否则
,当你长出来时,它会长回种子点。
Don't you want something like
instead of
Otherwise, when you grow out, it will grow back to the seed point.