上一次我们用了简单的直线和迭代法画点的形式画出了美丽的图形,但是自然界除了有其神奇的特性,更多地是有规律可寻的。
今天我们就要用递归来画出可以自己控制的图片!
?
我们先来介绍一下递归,所谓递归,就是自己的方法中还在调用自己的方法。但是实际上我们可以不用这样来考虑,我们就可以认为在方法中又调用了一个方法,
这个方法和自己的方法的用途一样,只是带入的参数不同。
在递归中我们要注意几点:
1、注意退出条件的控制,递归是个死循环,没有退出条件就会一直递归下去,直至栈溢出,然后报错。
2、递归时注意变量的传递和值的变化。
3、我们还要关注进入时的参数值变化和返回时返回值的变化。
?
首先我们来画一个递归画直线的:
class="java" name="code"> /** * 递归画直线的方法 * @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); } }
?
?