在应用程序中,我每次运行时都会向广场提供随机帧。我用这个逻辑来确保
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;
}
现在,方块总是在视图的稍微修改(较小)的矩形内,并且它们从不与玩家方块相交。好极了。但他们仍然相互重叠。为什么呢?
答案 0 :(得分: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);
}
请注意,我根本没有测试过。此外,根据情况,如果按钮没有有效位置,这可能会永远循环。根据您的问题,可能有一个比完全随机放置所有内容更好的解决方案。
答案 1 :(得分:1)
假设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)
为false(因为B.frame
不与C.frame
相交),CGRectIntersectsRect(button.frame, playerRect)
为false,!CGRectContainsRect(CGRectMake(10, 10, 300, 460), button.frame)
为false。所以你设置shouldContinue = NO
。
然后内循环退出。你测试shouldContinue
,发现它是假的,然后退出do / while循环。您已将按钮B与按钮A重叠。
答案 2 :(得分:0)
最后,这有效:(结合Rob Lourens和rob mayoff的精彩答案 - 谢谢你们,在这里,你们每个人都有一个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;
}
}
}