Java:随机生成不相交的圆(陷入while循环)

3

我希望在画布上创建随机圆形,但有一个限制条件:这些圆形之间不能相交。目前我已经想出了一种检测圆形是否相交的方法,如果它们相交,就会生成一个新的圆形。以下是我的思路和代码:

for(int i=0;i<amountRBC;i++)
        {
            xPosRBC[i]=random.nextInt(xSize);
            yPosRBC[i]=random.nextInt(ySize);
        }

在这里,我为每个红细胞生成一个随机的x和y位置(在xSize乘以ySize的画布内),共有amountRBC个红细胞(仅作演示,假设为5)。这些x和y位置会分别存储在数组xPosRBC[]和yPosRBC[]中。

for(int i=0;i<amountRBC;i++)
        {
            for(int j=0;j<amountRBC;j++)
            {
                while(Math.sqrt(Math.pow(Math.abs(xPosRBC[j]-xPosRBC[i]),2)+Math.pow(Math.abs(yPosRBC[j]-yPosRBC[i]), 2))<(2*rbcRadius))
                {
                    xPosRBC[i]=random.nextInt(xSize); //random starting position of bacterium
                    yPosRBC[i]=random.nextInt(ySize);
                    j=0;
                }
            }
        }

然后我检查每个点是否相距不超过圆的2倍半径(使用此sqrt((|xpos1-xpos2|)^2+(|ypos1-ypos2|)^2)公式),如果是,就会生成一个新的位置并重置“检查”循环(j=0)。 对于每个圆(从i=0到amountRBC),重复此过程。 在我的推理中,这应该得到5个随机放置的圆,它们之间的距离至少为2倍半径,这意味着它们不应相交。

然而,程序似乎无限期地陷入了这个while循环中,我找不出原因。

[注意]:屏幕上只有少量半径较小的圆。 这意味着不能填充圆时的情况不可能是问题所在。

非常感谢任何帮助!


如果算法卡住了,那么它可能随机生成了一个表面,在这个表面上添加非相交圆形是不可能的。只需添加一个失败计数器,如果连续生成太多相交圆,则中止算法。显示一些有关仅能设置 n 个圆形中的 m 个圆形的消息即可。 - M. Prokhorov
不是直接的解决方案,而是一个不同方法的想法:你可以将画布分成一个网格,比如说20x20个单元格,每个单元格足够大容纳一个“细菌”,然后循环遍历这些单元格,并以一定的概率创建一个“细菌”。概率可以从单元格数量和“amountRBC”计算得出。然后,如果要创建一个“细菌”,只需在单元格内随机化其位置,以使其不那么明显。这样,你只需要一个循环,耶!我感觉现在想玩一局Agario... - domsson
@M.Prokhorov 如果有很多圆的话,那么这是有道理的,但即使只需要绘制一个圆,它也会卡在循环内部。 - ItsTheSebbe
1
小改进:不要计算平方根,只需将其与2 * r的平方进行比较。 - user85421
1
如果你无论如何都平方差值,就没有必要先取绝对值。 - biziclop
3个回答

2

我刚刚找到了解决问题的方法。也就是说,在上述while循环中,它还比较了圆的大小和它自己的位置,因此距离始终为0。在while循环中,我添加了运算符(&& i!=j),现在看起来一切正常。谢谢大家!


1
和Persixty回答的一样。 - user85421
@CarlosHeuberger 是的。当我点击提交时,OP的答案出现了。注意:实际上有一种更有效的比较方法。这种方法将A与B进行比较,然后将B与A进行比较,从而基本上使工作量翻倍。 - Persixty

2
我认为您需要按照以下方式执行内部循环:
for(int j=0;j<amountRBC;j++) {
    if(j==i){
        continue;
    }

当前情况是,当j等于i时,它会发现圆形与自身相交,重新生成并重置j


0

我认为你不是卡在 while 循环中,而是在 for 循环中,因为你在 while 循环内部重置了内部 for 循环的计数器 j=0;,导致它永远不会结束。

使用一些打印输出来验证这点,你应该能看到你被卡住的位置。同时,打印输出(或者调试)可以帮助你看到哪个条件没有按照你期望的那样达成,以及其中的内容是什么。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接