首先我们先来明确什么是递归,才能充分感受到递归的神奇魅力!
- 递归 定义
递归就是不断调用自身函数或者方法的算法,它的实质就是把问题分解成规模缩小的同类问题的子问题,然后递归调用方法来表示问题的解。
- 递归特点
1)递归就是方法里调用自身。
2) 在使用递归时,必须有一个明确的递归结束条件,称为递归出口。
3)每次调用在规模上都有所缩小(通常是减半);
4)相邻两次重复之间有紧密的联系,前一次要为后一次做准备(通常前一次的输出就作为后一次的输入);
4)递归次数过多容易造成栈溢出等,因而每次递归调用都是有条件的(以规模未达到直接解答的大小为条件),无条件递归调用将会成为死循环而不能正常结束。
- 如何使用递归
我用递归方法画了Sierpinski 三角形和方格地毯
1)方格地毯
关键:在动作监听器里先确定好参数,将一个正方形的方法写出来,再调用draw方法就可,注意坐标间的数学关系,不要算错啦!刚一开始我没有充分掌握到递归的精髓,就无法理清各个正方形的关系。
以下为其代码
主方法
import java.awt.Color;
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
public class square {
public void initUI(){
JFrame jf=new JFrame();
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setSize(1000,800);
jf.setLocationRelativeTo(null);
jf.setBackground(Color.pink);
jf.setLayout(new FlowLayout());
JButton btn=new JButton("Draw");
jf.add(btn);
btnListener l=new btnListener();
btn.addActionListener(l);
jf.setVisible(true);
l.g=jf.getGraphics();
}
public static void main(String[]args){
square sq=new square();
sq.initUI();
}
}
动作监听器
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class btnListener implements ActionListener {
Graphics g;
public void actionPerformed(ActionEvent e){
int x=200;int y=300;int a=300;
draw(x, y, a, 3);
}
private void draw(int x,int y,int a,int n){
//若将int n=10写在这里,就是局部变量,每次运行都是十
if(n<=0){
return;
}
System.out.println("===="+n);
n--;
g.drawRect(x, y, a, a);
g.fillRect(x+a/3, y+a/3, a/3, a/3);
draw(x, y, a/3, n);
draw(x+a/3, y, a/3, n);
draw(x+a*2/3, y, a/3, n);
draw(x, y+a/3, a/3, n);
//draw(x+a/3, y+a/3, a/3, n);
draw(x+a*2/3, y+a/3, a/3, n);
draw(x, y+a*2/3, a/3, n);
draw(x+a/3, y+a*2/3, a/3, n);
draw(x+a*2/3, y+a*2/3, a/3, n);
(2)Sierpinski 三角形
关键:将最基本的图形框架画出来,画等边三角形的时候,坐标有浮点型的,需要先定义浮点型double,再将其转换成int型,要不然不同类型的坐标数据不能画出一根线来;然后就是确定好顶点
该图形的主方法与上面地毯的类似,主要是监听器里的方法不同
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class BtnListener implements ActionListener{
Graphics g;
@Override
public void actionPerformed(ActionEvent e) {
int x1 = 300,y1=600, length=400, n=10;
//因为其他两个坐标有小数,所以要变为浮点型
double x2,y2,x3,y3;
x2=x1+length;
y2=y1;
x3=x1+length/2;
y3=y1-length/2*Math.sqrt(3);
//因为画一条直线的两个坐标数字类型必须要一致,所以要将浮点型换位整型
int a1,b1,a2,b2,a3,b3;
a1=x1;b1=y1;
a2=(int)x2;b2=(int)y2;
a3=(int)x3;b3=(int)y3;
//接下来画三角形的三条边
g.drawLine(a1,b1,a2,b2);
g.drawLine(a1,b1,a3,b3);
g.drawLine(a2,b2,a3,b3);
//用draw方法将它们整到一起
draw(a1,b1,a2,b2,a3,b3,n);
}
private void draw(int a1,int b1,int a2,int b2,int a3,int b3, int n){
//终止条件
if(n<=0){
return;
}
System.out.println("===="+n);
n--;
//用数学的方法将要递归的三角形表示出来,关键是确定顶点的位置
int A1,B1,A2,B2,A3,B3;
A1=(a1+a2)/2;B1=(b1+b2)/2;
A2=(a1+a3)/2;B2=(b1+b3)/2;
A3=(a2+a3)/2;B3=(b2+b3)/2;
//draw方法的基本功能
g.drawLine(A1,B1,A2,B2);
g.drawLine(A1,B1,A3,B3);
g.drawLine(A2,B2,A3,B3);
draw(a1,b1,A1,B1,A2,B2,n);
draw(A2,B2,A3,B3,a3,b3,n);
draw(A1,B1,a2,b2,A3,B3,n);
}
}