CGRectIntersectsRect неточность логики - PullRequest
1 голос
/ 20 ноября 2011

В приложении я даю случайные кадры квадратам каждый раз, когда оно запускается. Я использую эту логику, чтобы убедиться,

а) каждый квадрат не слишком близко к игроку
и
б) каждый квадрат содержится внутри экрана в) ни один квадрат не касается другого квадрата

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 х 120 в центре экрана. Мой код неверен? Потому что я не получаю ни одной из этих функций.

Edit: я действительно получаю одну из желаемых черт этого метода: ни один квадрат никогда не пересекает 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;
            }

И теперь квадраты всегда находятся внутри слегка измененного (меньшего) прямоугольника для вида, и они никогда не пересекают квадрат игрока. Ура. Но они все равно появляются друг на друге. Почему?

Ответы [ 3 ]

1 голос
/ 20 ноября 2011

Предположим, 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.

1 голос
/ 20 ноября 2011

Это не проблема с 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);
}

Обратите внимание, что я вообще не проверял это. Кроме того, в зависимости от ситуации, это может зацикливаться вечно, если для кнопки нет действительной позиции. Может быть лучшее решение, чем размещать все случайным образом, в зависимости от вашей проблемы.

0 голосов
/ 20 ноября 2011

В конце концов, это сработало: (комбинация замечательных ответов Роба Лоуренса и Роба Майоффа, спасибо, ребята, и вот, у каждого из вас есть голос!))

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