CGRectIntersectsRect 逻辑不准确

发布于 2024-12-16 21:27:32 字数 1560 浏览 3 评论 0原文

在应用程序中,每次运行时我都会向方块提供随机帧。我使用这个逻辑来确保

a)每个方块都不会离玩家太近

b) 每个方块都包含在屏幕视图内 c)没有正方形接触任何其他正方形

for(UIButton* button in squareArray) {
    BOOL shouldContinue = YES;
    do {
        int randX = arc4random() % 321;
        int randY = arc4random() % 481;
        button.frame = CGRectMake(randX, randY, button.frame.size.width, button.frame.size.height);
        CGRect playerRect = CGRectMake(100, 180, 120, 120);
        for(UIButton* b in squareArray)
            if(!CGRectIntersectsRect(b.frame, button.frame) && 
                !CGRectIntersectsRect(button.frame, playerRect) && 
                CGRectContainsRect(self.view.frame, button.frame)) {
                shouldContinue = NO;
            }
    } while (shouldContinue);
}

使用此代码,我希望 squareArray 中的每个正方形(一旦循环完成)完全位于视图的边界内,不与数组中的任何其他按钮相交,并且完全超出了playerRect 矩形的边界,该矩形是屏幕中心的一个120 x 120 的正方形。我的代码有错吗?因为我没有获得这些功能。

编辑:事实上,我确实得到了此方法所需的特征之一:没有正方形与playerRect相交。但我仍然得到彼此重叠的方块和部分处于视野之外的方块。

编辑 2:

我对嵌套的 for 循环进行了这些更改:

for(UIButton* b in squareArray)
            if(![b isEqual:button]) {
                if(CGRectIntersectsRect(b.frame, button.frame) || 
                   CGRectIntersectsRect(button.frame, playerRect) || 
                   !CGRectContainsRect(CGRectMake(10, 10, 300, 460), button.frame))
                    shouldContinue = YES;
                else
                    shouldContinue = NO;
            }

现在,正方形始终位于稍微修改的(较小的)视图矩形内,并且它们从不与玩家正方形相交。耶。但它们仍然出现在彼此之上。为什么?

In an app I give random frames to squares every time it is run. I use this logic to make sure

a) each square is not too close to the player
and
b) each square is contained inside the view of the screen
c) no square touches any other square

for(UIButton* button in squareArray) {
    BOOL shouldContinue = YES;
    do {
        int randX = arc4random() % 321;
        int randY = arc4random() % 481;
        button.frame = CGRectMake(randX, randY, button.frame.size.width, button.frame.size.height);
        CGRect playerRect = CGRectMake(100, 180, 120, 120);
        for(UIButton* b in squareArray)
            if(!CGRectIntersectsRect(b.frame, button.frame) && 
                !CGRectIntersectsRect(button.frame, playerRect) && 
                CGRectContainsRect(self.view.frame, button.frame)) {
                shouldContinue = NO;
            }
    } while (shouldContinue);
}

With this code, I would expect that each square in squareArray would be (once the loop was complete) completely inside the boundaries of the view, not intersecting with any other of the buttons in the array, and completely outside the boundaries of the playerRect rect, which is a square 120 x 120 in the center of the screen. Is my code wrong? Because I get none of these functionalities.

Edit: I do in fact get one of the desired traits of this method: no square ever intersects playerRect. But I still get squares overlapping each other and squares that are partially out of the view.

Edit 2:

I have made these changes to the nested for loop:

for(UIButton* b in squareArray)
            if(![b isEqual:button]) {
                if(CGRectIntersectsRect(b.frame, button.frame) || 
                   CGRectIntersectsRect(button.frame, playerRect) || 
                   !CGRectContainsRect(CGRectMake(10, 10, 300, 460), button.frame))
                    shouldContinue = YES;
                else
                    shouldContinue = NO;
            }

And now the squares always are within the slightly modified (smaller) rect for the view, and they never intersect the player square. Yay. But they still appear on top of each other. Why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

凤舞天涯 2024-12-23 21:27:32

这不是 CGRectIntersectsRect 的问题,而是你的逻辑的问题。当内部循环找到一个不与按钮相交的 UIButton 时,您接受为按钮生成的随机坐标。您需要确保 squareArray 中的所有按钮都不与按钮相交,而不仅仅是一个。

另外,按钮的框架初始化为什么?也许这将是一个更好的解决方案:

for (int i=0; i<[squareArray count]; i++) {
    UIButton* button = [squareArray objectAtIndex:i];
    BOOL shouldContinue = NO;
    do {
        int randX = arc4random() % 321;
        int randY = arc4random() % 481;
        button.frame = CGRectMake(randX, randY, button.frame.size.width, button.frame.size.height);
        CGRect playerRect = CGRectMake(100, 180, 120, 120);
        for(int j=0; j<i; j++)
            UIButton *b = [squareArray objectAtIndex:j];
            if(CGRectIntersectsRect(b.frame, button.frame) || 
                CGRectIntersectsRect(button.frame, playerRect) || 
                !CGRectContainsRect(self.view.frame, button.frame)) {
                shouldContinue = YES;
            }
    } while (shouldContinue);
}

请注意,我根本没有测试过。此外,根据具体情况,如果按钮没有有效位置,则可能会永远循环。根据您的问题,可能有比完全随机放置所有内容更好的解决方案。

It's not a problem with CGRectIntersectsRect, it's a problem with your logic. When the inner loop finds a single UIButton that does not intersect button, you accept the random coords generated for button. You need to ensure that all the buttons in squareArray don't intersect button, not just one.

Also, what are the frames of the buttons initialized to? Maybe this would be a better solution:

for (int i=0; i<[squareArray count]; i++) {
    UIButton* button = [squareArray objectAtIndex:i];
    BOOL shouldContinue = NO;
    do {
        int randX = arc4random() % 321;
        int randY = arc4random() % 481;
        button.frame = CGRectMake(randX, randY, button.frame.size.width, button.frame.size.height);
        CGRect playerRect = CGRectMake(100, 180, 120, 120);
        for(int j=0; j<i; j++)
            UIButton *b = [squareArray objectAtIndex:j];
            if(CGRectIntersectsRect(b.frame, button.frame) || 
                CGRectIntersectsRect(button.frame, playerRect) || 
                !CGRectContainsRect(self.view.frame, button.frame)) {
                shouldContinue = YES;
            }
    } while (shouldContinue);
}

Note that I haven't tested that at all. Also, depending on the situation, this could loop forever if there is no valid position for a button. There may be a better solution than placing everything completely randomly, depending on your problem.

隔岸观火 2024-12-23 21:27:32

假设 squareArray 包含三个具有以下框架的按钮 A、B 和 C:

A.frame == CGRectMake(10,10,10,10)
B.frame == CGRectMake(10,10,10,10)
C.frame == CGRectMake(20,10,10,10)

请注意,A 和 B 重叠,但 A 和 B 不重叠 C。现在考虑当 按钮==B

第一次通过内部循环时,b == A,因此您检测到 CGRectIntersectsRect(b.frame, button.frame) 并设置 shouldContinue = YES< /代码>。

在第二遍中,b == B 表示[b isEqual:button],因此您什么也不做。

在第三次(也是最后一次)传递中,b == C。您发现 CGRectIntersectsRect(b.frame, button.frame) 为 false(因为 B.frame 不与 C.frame 相交),并且CGRectIntersectsRect(button.frame, playerRect) 为 false,并且 !CGRectContainsRect(CGRectMake(10, 10, 300, 460), Button.frame) 为 false。所以你设置了shouldContinue = NO。

然后内循环退出。您测试 shouldContinue,发现它是 false,然后退出 do/while 循环。左按钮 B 与按钮 A 重叠。

Suppose squareArray contains three buttons A, B, and C with these frames:

A.frame == CGRectMake(10,10,10,10)
B.frame == CGRectMake(10,10,10,10)
C.frame == CGRectMake(20,10,10,10)

Note that A and B overlap, but A and B do not overlap C. Now consider what happens in your inner loop when button == B.

On the first pass through the inner loop, b == A, so you detect CGRectIntersectsRect(b.frame, button.frame) and set shouldContinue = YES.

On the second pass, b == B which means [b isEqual:button], so you do nothing.

On the third (and final) pass, b == C. You find that CGRectIntersectsRect(b.frame, button.frame) is false (because B.frame does not intersect C.frame), and CGRectIntersectsRect(button.frame, playerRect) is false, and !CGRectContainsRect(CGRectMake(10, 10, 300, 460), button.frame) is false. So you set shouldContinue = NO.

Then the inner loop exits. You test shouldContinue, find that it's false, and exit the do/while loop. You have left button B overlapping button A.

成熟稳重的好男人 2024-12-23 21:27:32

最后,这成功了:(罗布·劳伦斯和罗布·梅奥夫的精彩答案的结合-谢谢大家,在这里,你们每个人都投了赞成票!:))

for(int iii = 0; iii < [squareArray count]; iii++) {

    int randX = arc4random() % 321;
    int randY = arc4random() % 481;

    [(UIButton*)[squareArray objectAtIndex:iii] setFrame:CGRectMake(randX, randY, [(UIButton*)[squareArray objectAtIndex:iii] frame].size.width, [(UIButton*)[squareArray objectAtIndex:iii] frame].size.height)];

    CGRect playerRect = CGRectMake(40, 120, 150, 150);

    for(UIButton* b in squareArray)

        if(![b isEqual:[squareArray objectAtIndex:iii]]) {

            if(CGRectIntersectsRect(b.frame, [(UIButton*)[squareArray objectAtIndex:iii] frame]))
            {
                iii--;
                break;
            } else if(CGRectIntersectsRect([(UIButton*)[squareArray objectAtIndex:iii] frame], playerRect)) {
                iii--;
                break;
            } else if(![self checkBounds:[(UIButton*)[squareArray objectAtIndex:iii] frame]]) {
                iii--;
                break;
            }
        }
}

In the end, this worked: (a combination of the wonderful answers of Rob Lourens and rob mayoff- thanks guys, and here, each of you have an upvote! :) )

for(int iii = 0; iii < [squareArray count]; iii++) {

    int randX = arc4random() % 321;
    int randY = arc4random() % 481;

    [(UIButton*)[squareArray objectAtIndex:iii] setFrame:CGRectMake(randX, randY, [(UIButton*)[squareArray objectAtIndex:iii] frame].size.width, [(UIButton*)[squareArray objectAtIndex:iii] frame].size.height)];

    CGRect playerRect = CGRectMake(40, 120, 150, 150);

    for(UIButton* b in squareArray)

        if(![b isEqual:[squareArray objectAtIndex:iii]]) {

            if(CGRectIntersectsRect(b.frame, [(UIButton*)[squareArray objectAtIndex:iii] frame]))
            {
                iii--;
                break;
            } else if(CGRectIntersectsRect([(UIButton*)[squareArray objectAtIndex:iii] frame], playerRect)) {
                iii--;
                break;
            } else if(![self checkBounds:[(UIButton*)[squareArray objectAtIndex:iii] frame]]) {
                iii--;
                break;
            }
        }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文