上一次我们用了简单的直线和迭代法画点的形式画出了美丽的图形,但是自然界除了有其神奇的特性,更多地是有规律可寻的。
今天我们就要用递归来画出可以自己控制的图片!
我们先来介绍一下递归,所谓递归,就是自己的方法中还在调用自己的方法。但是实际上我们可以不用这样来考虑,我们就可以认为在方法中又调用了一个方法,
这个方法和自己的方法的用途一样,只是带入的参数不同。
在递归中我们要注意几点:
1、注意退出条件的控制,递归是个死循环,没有退出条件就会一直递归下去,直至栈溢出,然后报错。
2、递归时注意变量的传递和值的变化。
3、我们还要关注进入时的参数值变化和返回时返回值的变化。
首先我们来画一个递归画直线的:
/**
* 递归画直线的方法
* @param g图形对象
* @param x1第一个点横坐标
* @param y1第一个点纵坐标
* @param x2第二个点横坐标
* @param y2第二个点纵坐标
* @param count递归次数
*/
public void drawline(Graphics g, int x1, int y1, int x2, int y2, int count) {
count--;
//如果count等于0就返回
if (count < 1) {
return;
}
g.drawLine(x1, y1, x2, y2);//画线
drawline(g, x1, y1 + 50, (int) (2.0 / 3 * x1 + 1.0 / 3 * x2), y2 + 50,
count);//递归画左边直线
drawline(g, x2, y2 + 50, (int) (2.0 / 3 * x2 + 1.0 / 3 * x1), y1 + 50,
count);//递归画右边直线
}
正方形:
/**
* 画正方形的方法
* @param g图形对象
* @param x正方形中心横坐标
* @param y正方形中心纵坐标
* @param r正方形边长的一半
* @param count迭代次数
*/
public void drawsquare(Graphics g, int x, int y, int r, int count) {
count--;
//如果count为0,返回
if (count < 1) {
return;
}
g.fillRect(x - r, y - r, 2 * r, 2 * r);//画正方形
//迭代画周围的8个小正方形
drawsquare(g, x - (int) (r * 2.5), y - (int) (r * 2.5), r / 3, count);
drawsquare(g, x, y - (int) (r * 2.5), r / 3, count);
drawsquare(g, x + (int) (r * 2.5), y - (int) (r * 2.5), r / 3, count);
drawsquare(g, x - (int) (r * 2.5), y, r / 3, count);
drawsquare(g, x + (int) (r * 2.5), y, r / 3, count);
drawsquare(g, x - (int) (r * 2.5), y + (int) (r * 2.5), r / 3, count);
drawsquare(g, x, y + (int) (r * 2.5), r / 3, count);
drawsquare(g, x + (int) (r * 2.5), y + (int) (r * 2.5), r / 3, count);
}
三角形:
/**
* 画三角形
* @param g图形对象
* @param x1上边的横坐标
* @param y1上边的纵坐标
* @param x2左边的横坐标
* @param y2左边的纵坐标
* @param x3右边的横坐标
* @param y3右边的纵坐标
* @param count画三角形的迭代次数
*/
public void drawtriangle(Graphics g, int x1, int y1, int x2, int y2,
int x3, int y3, int count) {
count--;//count减一
if (count < 1)//如果count小于1,返回
{
return;
}
//画线
g.drawLine(x1, y1, x2, y2);
g.drawLine(x1, y1, x3, y3);
g.drawLine(x3, y3, x2, y2);
//画中间的线
drawtriangle(g, (x1 + x2) / 2, (y1 + y2) / 2, x2, y2, (x2 + x3) / 2,
(y2 + y3) / 2, count);
drawtriangle(g, x1, y1, (x1 + x2) / 2, (y1 + y2) / 2, (x1 + x3) / 2,
(y1 + y3) / 2, count);
drawtriangle(g, (x1 + x3) / 2, (y1 + y3) / 2, x3, y3, (x2 + x3) / 2,
(y2 + y3) / 2, count);
}
Koch雪花:
/**
* 画雪花的方法
*
* @param g图形对象
* @param x1左边点的横坐标
* @param y1左边点的纵坐标
* @param x2右边点的横坐标
* @param y2右边点的纵坐标
* @param count画线的次数
*/
public void drawkoch(Graphics g, double x1, double y1, double x2,
double y2, int count) {
if (count <= 1) {
g.drawLine((int) x1, (int) y1, (int) x2, (int) y2);// 画线
} else {
double x3 = (2 * x1 + x2) / 3;// 第一个三等份点的x坐标
double y3 = (2 * y1 + y2) / 3;// 第一个三等份点的y坐标
double x4 = (x1 + 2 * x2) / 3;// 第二个三等份点的x坐标
double y4 = (y1 + 2 * y2) / 3;// 第二个三等份点的y坐标
double k = (x1 - x2) * (y1 - y2);// 线的斜率
double x5 = x1, y5 = y1;// 第一个三等份点的x坐标
if (y3 == y4)// 直线
{
x5 = (x3 + x4) / 2;
y5 = y3 - (x4 - x3) * Math.sqrt(3) / 2;
} else if (k < 0)// 左斜线
{
x5 = x1;
y5 = y4;
} else if (k > 0)// 右斜线
{
x5 = x2;
y5 = y3;
}
if (x3 == x4) // 如果斜线为竖线
{
x5 = x3;
y5 = y3;
}
// 画尖端的左面那条线
drawkoch(g, x3, y3, x5, y5, count - 1);
// 画尖端的右面那条线
drawkoch(g, x5, y5, x4, y4, count - 1);
// 画左边那条直线
drawkoch(g, x1, y1, x3, y3, count - 1);
// 画右边那条直线
drawkoch(g, x4, y4, x2, y2, count - 1);
}
}