Java 随机画一个圆圈,将不与另一个圆圈相交的圆圈涂成红色

Java 随机画一个圆圈,将不与另一个圆圈相交的圆圈涂成红色,java,arrays,swing,geometry,jpanel,Java,Arrays,Swing,Geometry,Jpanel,我有一个Java Swing任务,目标如下: 当程序启动时,它绘制20个未填充的圆,每个圆的半径和位置随机确定 如果圆的周长线不与任何其他圆相交,请用红色绘制圆的轮廓。如果它至少与另一个圆相交,则用黑色绘制 添加一个按钮,每次按下该按钮时,都会创建一组新的圆,如上所述 我已经完成了上面的目标1和目标3,但我在目标2上被难住了 在介绍代码之前,让我先介绍一下我对代码背后的数学知识的理解。一个圆不能与另一个圆相交有两种方式: 这些圆相距太远,无法共享一个周长点,即它们中心之间的距离大于半径之和(d>

我有一个Java Swing任务,目标如下:

  • 当程序启动时,它绘制20个未填充的圆,每个圆的半径和位置随机确定
  • 如果圆的周长线不与任何其他圆相交,请用红色绘制圆的轮廓。如果它至少与另一个圆相交,则用黑色绘制
  • 添加一个按钮,每次按下该按钮时,都会创建一组新的圆,如上所述 我已经完成了上面的目标1和目标3,但我在目标2上被难住了

    在介绍代码之前,让我先介绍一下我对代码背后的数学知识的理解。一个圆不能与另一个圆相交有两种方式:

  • 这些圆相距太远,无法共享一个周长点,即它们中心之间的距离大于半径之和(d>r1+r2)
  • 一个圆完全位于另一个圆内,其周长不接触,即其中心之间的距离小于其半径之间的差值(d<| r1-r2 |) 到目前为止我得到的信息:

  • 为了比较圆,必须在绘制圆之前指定圆,因此我使用for循环在数组中存储了20个值,用于中心坐标(int[]x,int[]y)和半径(double[]radius)
  • 接下来,我使用嵌套for循环遍历数组并比较两个圆,除非将一个圆与自身进行比较(索引j=索引k)。如果圆相交,则g.setColor(Color.RED)。如果不是,g.setColor(颜色为黑色)
  • 当我执行代码时,没有任何重叠的圆被正确地涂成红色。但是,一些重叠的圆也被涂成红色。我假设它们在绘制时不重叠,但在绘制后相交。如何修复代码以及时解释此差异?(问题区域位于底部附近,在相交圆类中)

    导入java.awt.BorderLayout;
    导入java.awt.event.ActionListener;
    导入java.awt.event.ActionEvent;
    导入java.awt.Color;
    导入java.awt.Graphics;
    导入javax.swing.JPanel;
    导入javax.swing.JFrame;
    导入javax.swing.JButton;
    公共类ButtonFrame扩展了JFrame
    {
    私有最终JButton resetButton=新JButton(“重置”);
    公共按钮框架()
    {
    超级(“绘制随机圈”);
    setLayout(新的BorderLayout());
    相交圆相交圆=新的相交圆();
    添加(相交圆、边界布局、中心);
    添加(重置按钮,BorderLayout.SOUTH);
    此.setDefaultCloseOperation(关闭时退出);
    这个。设置大小(14001400);
    ButtonHandler处理程序=新建ButtonHandler();
    resetButton.addActionListener(处理程序);
    }
    私有类ButtonHandler实现ActionListener
    {       
    @凌驾
    已执行的公共无效操作(操作事件)
    {
    重置();
    }
    }
    公共静态void main(字符串[]args)
    {
    ButtonFrame ButtonFrame=新的ButtonFrame();
    buttonFrame.setVisible(真);
    }
    公共无效重置()
    {
    ButtonFrame ButtonFrame=新的ButtonFrame();
    buttonFrame.setVisible(真);
    }
    }
    类相交圆扩展了JPanel
    {   
    私有静态最终JButton resetButton=新JButton(“重置圆”);
    私有静态最终JFrame=新JFrame(“相交圆”);
    @凌驾
    公共组件(图形g)
    {
    超级组件(g);
    这个.背景(颜色.白色);
    int[]x=新的int[20];
    int[]y=新的int[20];
    int[]直径=新int[20];
    双精度[]半径=新双精度[20];
    对于(int i=0;i<20;i++)
    {
    int xCoord=(int)(Math.random()*600);
    int yCoord=(int)(Math.random()*600);
    int circleSize=(int)(Math.random()*550);
    x[i]=xCoord;
    y[i]=yCoord;
    直径[i]=圆形;
    半径[i]=圆圈大小/2.0;
    }
    对于(int j=0;j<20;j++)
    {   
    对于(int k=0;k<20;k++)
    {   
    如果(k!=j)
    {
    if((数学sqrt((x[k]-x[j])*(x[k]-x[j])+(y[k]-y[j]))
    *(y[k]-y[j])>(半径[j]+半径[k]))||
    ((数学sqrt((x[k]-x[j])*(x[k]-x[j])+(y[k]-y[j]))
    *(y[k]-y[j])<(Math.abs(半径[j]-radius[k]))
    g、 setColor(Color.RED);
    其他的
    g、 设置颜色(颜色为黑色);
    g、 拉深椭圆(x[j],y[j],直径[j],直径[j]);
    }
    其他的
    继续;
    }
    }
    }
    }
    
    循环内的
    if
    语句中存在逻辑错误-您可以设置黑色,然后将其他对圆还原为红色。可能的解决方案草案:

      for (int j = 0; j < 20; j++)
        {   
            g.setColor(Color.RED);  //set non-intersect state
            for (int k = j + 1; k < 20; k++)  //avoid excessive work
            {   
                    if (intersect test)
                      {
                        g.setColor(Color.BLACK);
                        break; //can stop here
                      };
                g.drawOval(x[j], y[j], diameter[j], diameter[j]);
            }
    }
    
    for(int j=0;j<20;j++)
    {   
    g、 setColor(Color.RED);//设置不相交状态
    对于(int k=j+1;k<20;k++)//避免过度工作
    {   
    if(交叉测试)
    {
    g、 设置颜色(颜色为黑色);
    break;//可以停在这里
    };
    g、 拉深椭圆(x[j],y[j],直径[j],直径[j]);
    }
    }
    
    因为这是一项作业,所以我只给出一个提示。将识别圆重叠和标记圆重叠真/假(步骤2)的逻辑与绘制颜色边界(步骤3)完全分离。不要试图同时执行第2步和第3步。可以看到这样一个分离的例子。“我已经完成了上面的目标1和目标3,但我在目标2上遇到了困难。”假设你们确定交叉点的方式没有限制,我会这样做
      for (int j = 0; j < 20; j++)
        {   
            g.setColor(Color.RED);  //set non-intersect state
            for (int k = j + 1; k < 20; k++)  //avoid excessive work
            {   
                    if (intersect test)
                      {
                        g.setColor(Color.BLACK);
                        break; //can stop here
                      };
                g.drawOval(x[j], y[j], diameter[j], diameter[j]);
            }
    }