本章使用动态数组的方式来实现,将每一个点存入数组中并且找到是否计算过相同两点的中点坐标来避免重复计算。中点中标有一个随机浮动的范围。
1.创建线类来存储两点坐标以及他们的中点。
重写有参构造,传入x1,y1,x2,y2直接赋值。
package lcr0403.Draw;
import java.util.Random;
public class Line {
int x1, y1, x2, y2;
int midX = (x1 + x2) / 2, midY = (y1 + y2) / 2;
//有参构造
public Line(int x1, int y1, int x2, int y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
public Line(){
}
}
将中点x与y坐标进行保留,通过写方法时直接赋值。
2.创建线数据类型的数组
package lcr0403.Draw;
public class LineArray {
Line[] lineArr;
int size = 0;
int index = 0;
public LineArray(int size) {
this.lineArr = new Line[size];
}
//寻找是否具有相同的线,没有返回-1;
public int findLine(Line line) {
Line temLine = new Line(line.x2, line.y2, line.x1, line.y1);
/*System.out.println("x2:"+line.x2+" y2:"+line.y2+" x1:"+line.x1+" y1:"+line.y1);*/
if(size == 1){
return -1;
}
for (int i = 0; i < size-1; i++) {
if (lineArr[i].x1 == line.x1 &&lineArr[i].x2 == line.x2&&lineArr[i].y1 == line.y1&&lineArr[i].y2 == line.y2) {
return i;
} else if (lineArr[i].x1 == temLine.x1 &&lineArr[i].x2 == temLine.x2&&lineArr[i].y1 == temLine.y1&&lineArr[i].y2 == temLine.y2) {
return i;
}
}
return -1;
}
//添加元素
public int addLine(int x1, int y1, int x2, int y2) {
lineArr[index] = new Line(x1, y1, x2, y2);
index++;
size++;
return index-1;
}
}
定义数组并且定义大小,将构造方法改为有参构造,传进size,创建数组的大小。
后编写方法,我们需要两个,一个是进行添加元素的方法,添加完成后返回添加元素的下标,以便后来的使用。
第二个方法为寻找相同的两点,在寻找时我们要顺着找一遍以及反着找一次,找到返回下标,便于调出中点。没有则返回-1,重新传入中点即:(x1,y1,x2,y2)以及(x2,y2,x1,y1),在findLine方法中将传入线的数据两点进行对调。当size=1时那么为第一次传入的数据没有相同的点,直接返回-1。在判断是否相同时,要注意将两个坐标的个点拉出来进行对比,如果直接比lineArr[i] == line||lineArr[i] == temline.那么在我们定义的Line类中除了两点坐标还有中点坐标,会导致一直找不到,出现画的图形出现交叉的情况。
3.鼠标监听中画出图形的方法
LineArray la = new LineArray(10000);
public void draw(int x1, int y1, int x2, int y2, int x3, int y3, int r, int n) {
Random ran = new Random();
if (r <= 1) {
Polygon pol = new Polygon();
pol.addPoint(x1, y1);
pol.addPoint(x2, y2);
pol.addPoint(x3, y3);
g.drawPolygon(pol);
return;
}
if (n < 0) {
Polygon pol = new Polygon();
pol.addPoint(x1, y1);
pol.addPoint(x2, y2);
pol.addPoint(x3, y3);
g.drawPolygon(pol);
return;
}
int m1x, m1y, m2x, m2y, m3x, m3y;
//存线,返回下标
int index1 = la.addLine(x1, y1, x2, y2);
/*System.out.println("index1:"+index1);*/
//寻找线返回下标
int indexMid1 = la.findLine(la.lineArr[index1]);
/*System.out.println("indexMid1:"+indexMid1);*/
if (indexMid1 == -1) {
//如果没有线的中点
m1x = la.lineArr[index1].midX = (x1 + x2) / 2 + ran.nextInt(2 * r) - r;
m1y = la.lineArr[index1].midY = (y1 + y2) / 2 + ran.nextInt(2 * r) - r;
} else {
//找到线的中点
m1x = la.lineArr[indexMid1].midX;
m1y = la.lineArr[indexMid1].midY;
}
//点一与点三
int index2 = la.addLine(x1, y1, x3, y3);
/*System.out.println("index2:"+index2);*/
//寻找线返回下标
int indexMid2 = la.findLine(la.lineArr[index2]);
/*System.out.println("indexMid2:"+indexMid2);*/
if (indexMid2 == -1) {
m2x = la.lineArr[index2].midX = (x1 + x3) / 2 + ran.nextInt(2 * r) - r;
m2y = la.lineArr[index2].midY = (y1 + y3) / 2 + ran.nextInt(2 * r) - r;
} else {
m2x = la.lineArr[indexMid2].midX;
m2y = la.lineArr[indexMid2].midY;
}
//点二与点三
int index3 = la.addLine(x2, y2, x3, y3);
/*System.out.println("index3:"+index3);*/
//寻找线返回下标
int indexMid3 = la.findLine(la.lineArr[index3]);
/*System.out.println("indexMid3:"+indexMid3);*/
if (indexMid3 == -1) {
m3x = la.lineArr[index3].midX = (x3 + x2) / 2 + ran.nextInt(2 * r) - r;
m3y = la.lineArr[index3].midY = (y3 + y2) / 2 + ran.nextInt(2 * r) - r;
} else {
m3x = la.lineArr[indexMid3].midX;
m3y = la.lineArr[indexMid3].midY;
}
r *= 0.5;
n--;
/*System.out.println("m1x:"+m1x+" m1y:"+m1y+" m2x"+m2x+" m2y:"+m2y+" m3x:"+m3x+" m3y:"+m3y);*/
draw(x1, y1, m1x, m1y, m2x, m2y, r, n);
draw(m1x, m1y, x2, y2, m3x, m3y, r, n);
draw(m2x, m2y, m3x, m3y, x3, y3, r, n);
draw(m3x, m3y, m2x, m2y, m1x, m1y, r, n);
}
r为中点坐标浮动范围,n为调用次数
首先定义一个随机数,并且定义m1x,m1y等表示两点间中点的坐标,首先调用刚刚LineArray数组中的添加元素方法,将我们的坐标输入其中,用index1来接受返回的下标,接着调用findLine方法将刚刚添加的线进行查找,找到返回下标,没找到返回-1,接着判断indexMid1的值,为-1则没有相同点中点的坐标,那么将中点m1x与m1y存入最新线的中点坐标中,找到则直接调用之前的中点坐标。同理完成另外两个中点坐标。随着递归的进行r浮动范围逐步减小。每次进行后n减一,接着将三角形分为四个区域,分别进行递归。完成后在递归开始写入递归结束方法,当n小于0时结束,并画出当前最小的三角形,以及当r <= 1时结束,r小于这个范围会导致随机数的bound小于等于0无法进行随机数的计算报错。