【问题标题】:CGRectIntersectsRect logic inaccuracyCGRectIntersectsRect 逻辑不准确
【发布时间】:2011-11-20 01:40:49
【问题描述】:

在一个应用程序中,我每次运行时都会给正方形随机帧。我用这个逻辑来确保

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 rect,它是屏幕中心的 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;
            }

现在方块总是在视图的略微修改(更小)的矩形内,并且它们永远不会与玩家方块相交。耶。但它们仍然出现在彼此之上。为什么?

【问题讨论】:

  • 您没有提出问题或解释您认为代码有什么问题。
  • Bahahaha 对不起,我在实际提问之前不小心发布了它,因为我很着急。正在更新中...

标签: objective-c cocoa-touch cgrect


【解决方案1】:

这不是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);
}

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

【讨论】:

  • 帧是通过IB初始化的,因为squareArray中的每个方块都是一个UIButton的IBOutlet,所以它们都有默认位置,我只是想随机化它们。
  • 你确定你已经得到了 squareArray 中的所有方块吗?如果它们来自笔尖,也许有些你没有重新定位?
  • 否;我知道正确数量的正方形被加载到数组中,因为在启动时,根据 应该 在数组中的正方形数量(取决于用户选择),这些正方形是硬编码的进入数组。此外,由于两次都使用同一个数组,如果它不包括所有正方形(有四个),那么每次都不会将它们全部放在随机位置,它们是。
【解决方案2】:

假设 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。现在考虑当 button == B 时,您的内部循环中会发生什么。

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

在第二次通过时,b == B 表示[b isEqual:button],所以你什么都不做。

在第三次(也是最后一次)通过时,b == C。你发现CGRectIntersectsRect(b.frame, button.frame) 为假(因为B.frame 不与C.frame 相交),CGRectIntersectsRect(button.frame, playerRect) 为假,!CGRectContainsRect(CGRectMake(10, 10, 300, 460), button.frame) 为假。所以你设置shouldContinue = NO

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

【讨论】:

  • 因此,换句话说,删除您设置 shouldContinue = NO 的行。
  • 我有一个很长的解释为什么这不起作用,我正要发布它并寻求更多帮助,但后来我决定坚持下去并弄清楚我自己。删除该行是行不通的,因为即使条件得到满足,从它不满足的那一刻起,shouldContinue 仍然是 YES,并且你会得到一个无限循环。我刚刚发布了可行的解决方案。
【解决方案3】:

最后,这奏效了:(结合了 Rob Lourens 和 rob mayoff 的精彩回答——谢谢大家,在这里,你们每个人都有一个赞成票!:))

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;
            }
        }
}

【讨论】:

    猜你喜欢
    • 2019-12-22
    • 1970-01-01
    • 2010-12-06
    • 2018-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-08
    • 2021-01-16
    相关资源
    最近更新 更多