该程序绘制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);
}
}
}
}
另外如果你注意到我的for循环只计数到5但我得到10个圆圈。我只是想知道为什么会这样?
答案 0 :(得分:4)
这里有几个问题。
setBackground(Color)
。此方法仅用于绘画。其他修改应在构造函数或init
方法super.paint(g)
作为被覆盖的paint
方法的第一行。这将清除背景posX
等)关于圈子的位置:
目前,每次重新绘制小程序时,您都会计算圈子的新位置和直径。因此,当您调整applet查看器的窗口大小时,随机放置的新圆圈将会四处闪烁。您应该只创建一次一次(可能在构造函数中)。在paint
方法中,您应该只绘制它们。
更重要的是:如何知道可能放置圆圈没有重叠?最后,这会导致复杂的Circle Packing世界,您可以在其中使用一些真正复杂的技术,以确保尽可能紧密地放置圆圈。
但是现在,您可以使用非常简单的方法:每次创建新的圆圈时,您都可以尝试(多次)指定新的位置和直径,直到找到与现有圆圈不重叠的配置。虽然使用像
这样的方法似乎很诱人while (existingCircles.size() < 5)
{
Circle circle = newRandomCircle();
if (!circle.overlapsAny(existingCircles))
{
existingCircles.add(circle);
}
}
这里的问题是,当无法放置圆圈时,此算法不会终止! (注意:这是伪代码。但是......你应该考虑以某种方式编写代码,使它看起来像上面的代码。也就是说,考虑创建一个Circle
类。)
然而,这是一个非常务实的解决方案,它只试图放置一个新的圆圈10次,并且当它没有成功时根本不放置它。虽然这不是很优雅,但它至少可以保证终止。
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);
}
}
}
答案 1 :(得分:1)
要绘制不重叠的圆圈,您需要检查新圆圈是否会与已定义的圆圈相交。
您可能想要将#Tries计数器添加到#2/3 - 例如,如果它找不到第四个或第五个圆圈的好位置,它可能会永远循环。如果#Tries计数器超过某个限制,请转到#1;基本上,从头开始。