首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用于检查相交的慢速foreach循环

用于检查相交的慢速foreach循环
EN

Code Review用户
提问于 2014-05-12 20:21:29
回答 2查看 1.5K关注 0票数 5

我试图做一个循环,它返回一个矩形是否碰撞,然后向哪个和弦移动该矩形。

我这样称呼我的职能:

代码语言:javascript
运行
复制
rectangles2[i].rect = rectangleupdated(i, rectangles2);

这就是我的功能:

代码语言:javascript
运行
复制
private Rectangle rectangleupdated(int i, List<rectList> rectangles2)
{
    //fills rectangles with rectangles to check intersect with
    BOTTOM = rectangles2[i].rect;
    BOTTOM_LEFT = rectangles2[i].rect;
    BOTTOM_RIGHT = rectangles2[i].rect;
    //bool to be set to false if intersects returns true
    bBOTTOM = true;
    bBOTTOM_LEFT = true;
    bBOTTOM_RIGHT = true;
    //move the intersect rectangles
    BOTTOM.Y++;
    BOTTOM_LEFT.Y++;
    BOTTOM_LEFT.X--;
    BOTTOM_RIGHT.Y++;
    BOTTOM_RIGHT.X++;

    foreach (rectList rects in rectangles2)
    {
        if (!rects.type.Contains("bg"))
        {
            if (rectangles2[i].rect.Y < 500)
            {
                if (BOTTOM.IntersectsWith(rects.rect))
                {
                    bBOTTOM = false;
                }
                else if (BOTTOM_LEFT.IntersectsWith(rects.rect))
                {
                    bBOTTOM_LEFT = false;
                }
                else if (BOTTOM_RIGHT.IntersectsWith(rects.rect))
                {
                    bBOTTOM_RIGHT = false;
                }
            }
            else
            {
                return rectangles2[i].rect;
            }
        }
    }
    if (bBOTTOM == true) return BOTTOM;
    else if (bBOTTOM_RIGHT == true) return BOTTOM_RIGHT;
    else if (bBOTTOM_LEFT == true) return BOTTOM_LEFT;
    return rectangles2[i].rect; 
}

我想我知道为什么它会这么慢,但我不知道如何修复它/使这段代码更有用。

EN

回答 2

Code Review用户

发布于 2014-05-13 12:39:51

你确定你真的应该在这里使用else if吗?我认为你只需要使用if。因为另一个rect可以同时与左下角和右下角同时碰撞。

代码语言:javascript
运行
复制
if (BOTTOM.IntersectsWith(rects.rect))
{
    bBOTTOM = false;
}
else if (BOTTOM_LEFT.IntersectsWith(rects.rect))
{
    bBOTTOM_LEFT = false;
}
else if (BOTTOM_RIGHT.IntersectsWith(rects.rect))
{
    bBOTTOM_RIGHT = false;
}

现在,我相信有一个更有效的方法来做到这一点。我想称之为..。

更多数学,更少代码

不要使用代码和测试冲突,而是使用Rectangle对象上可用的更多数学和方法,并使用它们进行计算。

我相信你能做到这一点。我没有时间用C#计算出确切的代码(部分原因是我不是C#专家)。我不知道它会有多高的效率,我也不完全确定它是否会起作用,但我认为它应该是正确的,而且是有效的:

这里的想法是计算所有矩形交叉口的总和,你将通过移动得到。

代码语言:javascript
运行
复制
MovingRect = the rectangle you want to move
MovingRect.y++
intersection = empty rectangle
for each (`rect` in all other rectangles) {
    if (rect intersects with MovingRect) {
        thisIntersection = calculate how much / where it intersects: See link below
        intersection = union of intersection with thisIntersection: See link below
        if the width of the intersection is two or more, then you can't move at all.
    }
}
check the size and position of the `intersection` rectangle:
  if it's size is nonexistent (i.e. empty rectangle), then you are free to move down one step
  else if it's width is 2 or more, then you are unable to move at all
  else if it's position is in the lower-left area of your rectangle, move right one step
  else if it's position is in the lower-right area of your rectangle, move left one step
  else throw an AssertionError because something is apparently wrong with this logic.

链接:

用于计算交叉口面积

对于矩形的合并

票数 5
EN

Code Review用户

发布于 2014-05-12 20:27:52

我建议的唯一更改是,在不知道您试图完成什么任务的情况下,将一个条件添加到foreach循环的末尾(E:实际上,最好在条件符中的if之后添加一个条件,因为布尔值只有在代码执行、更新以反映这一点时才会有所不同):

代码语言:javascript
运行
复制
if (rectangles2[i].rect.Y < 500)
{
    ...

    if (!bBOTTOM && !bBOTTOM_RIGHT && !bBOTTOM_LEFT)
    { return rectangles2[i].rect; }
}

避免在矩形中循环,即使我们已经知道它没有空间。

至于剩下的事情,如果你不知道你想要完成什么,那就很难了。如果上面、左边或右侧的一个点完全打开,则算法只将矩形移动到一个新的空间中。这就是你需要的行为吗?还有其他算法可以工作,您可以使用这些算法简单地将所有矩形彼此移开,但不一定会在每次运行时进入一个空空间。会发生这样的事情:

代码语言:javascript
运行
复制
foreach (rectList rects in rectangles2)
{
    if (!rects.type.Contains("bg"))
    {
        if (rectangles2[i].rect.Y < 500)
        {
            if (rectangles2[i].rect.IntersectsWith(rects.rect))
            {
                Rectangle returnRect = rectangles2[i].rect;
                if (rects.rect.X < rectangles2[i].rect.X)
                { returnRect.X++; }
                else if (rects.rect.X > rectangles2[i].rect.X)
                { returnRect.X--; }
                if (rects.rect.Y < rectangles2[i].rect.Y)
                { returnRect.Y++; }
                else if (returnRect.Y > rectangles2[i].rect.Y)
                { returnRect.Y--; }
                return returnRect;
            }
        }
    }
}

return rectangles2[i].rect;

这将返回一个从与其相交的第一个矩形移开的矩形。这个调的东西可能比你使用的更快,这取决于它是否适合你的需要。

我还建议像rects这样的对象的公共属性(它似乎是'rectList‘类型的,但只有一个矩形与它关联?)在PascalCase中命名,要容易得多。

票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/49563

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档