Java小程序:绘制不带';不要互相重叠?

Java小程序:绘制不带';不要互相重叠?,java,applet,geometry,Java,Applet,Geometry,该程序以随机直径在随机位置绘制10个圆。如果圆的直径小于25,则填充为黄色,大于50,则填充为绿色,否则将绘制为红色 我的问题是我不知道如何阻止这些圆相互重叠 这就是我到目前为止所做的: import java.util.Random; import java.awt.*; import javax.swing.JApplet; public class Circles extends JApplet{ public void paint(Graphics g) { Rand

该程序以随机直径在随机位置绘制10个圆。如果圆的直径小于25,则填充为黄色,大于50,则填充为绿色,否则将绘制为红色

我的问题是我不知道如何阻止这些圆相互重叠

这就是我到目前为止所做的:

import java.util.Random;
import java.awt.*;
import javax.swing.JApplet;

public class Circles extends JApplet{   

public void paint(Graphics g) {

    Random rand = new Random();
    int diameter = 0;
    int posX = 0;
    int posY = 0;

    setBackground(Color.CYAN);

    for(int i=1; i <= 5 ; i++ )
    {
        posX = rand.nextInt(500);
        posY = rand.nextInt(500);
        diameter = rand.nextInt(75)+1;

        if (diameter < 25)
        {
            g.setColor(Color.YELLOW);
            g.fillOval(posX, posY,diameter,diameter);
        }

        else if(diameter > 50)
        {
            g.setColor(Color.GREEN);
            g.fillOval(posX, posY,diameter,diameter);
        }
        else
        {
            g.setColor(Color.RED);
            g.drawOval(posX, posY,diameter,diameter);
        }


    }
}
}
import java.util.Random;
导入java.awt.*;
导入javax.swing.JApplet;
公共阶级圈子扩大
公共空间涂料(图g){
Random rand=新的Random();
内径=0;
int posX=0;
int-posY=0;
挫折背景(颜色:青色);
对于(int i=1;i 50)
{
g、 setColor(Color.GREEN);
g、 圆角(posX、posY、直径、直径);
}
其他的
{
g、 setColor(Color.RED);
g、 Draw椭圆形(posX、posY、直径、直径);
}
}
}
}

另外,如果你注意到我的for循环只计算到5,但我得到10个圈。我只是想知道为什么会这样?

若要绘制不重叠的圆,需要检查新圆是否与已定义的圆相交

  • 初始化空堆栈
  • 随机选取x、y和半径(直径的1/2)
  • 在堆栈上循环并使用(简单!)数学计算到每个其他圆中心的距离。如果此距离小于其半径+新半径,则不会接触
  • 如果是,请转到2
  • 如果它不接触任何其他圆,则将其添加到堆栈中
  • 如果堆栈的长度小于5,请转到2
  • 在堆栈上循环并绘制每个圆

  • 您可能需要在#2/3上添加一个#trys counter——例如,如果它找不到第四个或第五个圆的好位置,它可能会永远循环。如果#trys计数器超过某个限制,请转到#1;基本上,从零开始。

    这里有几个问题

    • 在绘制方法中不要调用
      setBackground(Color)
      。此方法仅用于绘画。其他修改应在构造函数或
      init
      方法中完成
    • 调用
      super.paint(g)
      作为重写的
      paint
      方法的第一行。这将清除背景
    • (次要:使变量的范围尽可能小。因此只在真正需要的地方声明
      posX
      等)
    关于圆圈的位置:

    目前,每次重新绘制小程序时,您都要计算圆的新位置和直径。因此,当您调整小程序查看器窗口的大小时,新的、随机放置的圆圈将在四周闪烁。您应该只创建一次圆(可能在构造函数中)。在
    绘制
    方法中,只应绘制它们

    更重要的是:您如何知道可以放置不重叠的圆?最后,这将导致进入一个复杂的世界,在那里你可以使用一些非常复杂的技术来确保你尽可能紧密地放置圆圈

    但现在,您可以使用一种非常简单的方法:每次创建一个新的圆时,您可以尝试(多次)指定一个新的位置和直径,直到找到一个不与现有圆重叠的配置。尽管使用这样的方法似乎很有诱惑力

    while (existingCircles.size() < 5)
    {
        Circle circle = newRandomCircle();
        if (!circle.overlapsAny(existingCircles))
        {
            existingCircles.add(circle);
        }
    }
    

    回答得很透彻,解释得很好。谢谢:D
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Point;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    
    import javax.swing.JApplet;
    
    public class Circles extends JApplet
    {   
        private final List<Point> positions;
        private final List<Integer> diameters;
    
        public Circles()
        {
            positions = new ArrayList<Point>();
            diameters = new ArrayList<Integer>();
    
            Random rand = new Random();
    
            for(int i=1; i <= 5 ; i++ )
            {
                int tries = 10;
                for (int t=0; t<tries; t++)
                {
                    int diameter = rand.nextInt(75)+1;
                    int posX = rand.nextInt(500);;
                    int posY = rand.nextInt(500);
                    Point position = new Point(posX, posY);
    
                    if (!overlapsOther(position, diameter))
                    {
                        positions.add(new Point(posX, posY));
                        diameters.add(diameter);
                        break;
                    }
                }
            }
        }
    
        private boolean overlapsOther(Point position, int diameter)
        {
            int radius = diameter/2;
            int centerX = position.x + radius;
            int centerY = position.y + radius;
    
            for (int i=0; i<positions.size(); i++)
            {
                Point otherPosition = positions.get(i);
                int otherDiameter = diameters.get(i);
                int otherRadius = otherDiameter/2;
                int otherCenterX = otherPosition.x + otherRadius;
                int otherCenterY = otherPosition.y + otherRadius;
    
                int dx = centerX - otherCenterX;
                int dy = centerY - otherCenterY;
                double distance = Math.hypot(dx, dy);
                if (distance < radius + otherRadius)
                {
                    return true;
                }
            }
            return false;
        }
    
        @Override
        public void paint(Graphics g) 
        {
            super.paint(g);
    
            for(int i=0; i<positions.size(); i++)
            {
                int posX = positions.get(i).x;
                int posY = positions.get(i).y;
                int diameter = diameters.get(i);
    
                if (diameter < 25)
                {
                    g.setColor(Color.YELLOW);
                    g.fillOval(posX, posY,diameter,diameter);
                }
    
                else if(diameter > 50)
                {
                    g.setColor(Color.GREEN);
                    g.fillOval(posX, posY,diameter,diameter);
                }
                else
                {
                    g.setColor(Color.RED);
                    g.drawOval(posX, posY,diameter,diameter);
                }
    
                System.out.println(diameter);
            }
        }
    }