分形之谢宾斯基三角形
本次课程是通过递归的方法来实现分形的操作。
递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。(以上参考专业资料)
用自己的话来说,如果实现一个目的,需要调用多次类似的方法,那么,我们就可以用到递归,而递归正确的重要条件是要有退出的条件,否则,递归将很有可能变成死递归,就像循环中的死循环一样。
那么,接下来是实现谢宾斯基三角形的递归方法:
public class Digui extends JFrame{
//private int count=0;
/**Digui类继承JFrame类
* @param args
*/
public static void main(String[] args) {
//实例化一个Digui对象,并设置相关属性
Digui di=new Digui();
di.setTitle("超级三角形");
di.setSize(500,500);
di.setLocationRelativeTo(null);
di.setDefaultCloseOperation(3);
di.setVisible(true);
//获取di对象的画布
Graphics g=di.getGraphics();
}
public void shower(double x1,double y1,double x2,double y2,double x3,double y3,Graphics g,int count){
//计数变量作用
count++;
//划线
g.drawLine((int)x1,(int)y1,(int)x2,(int)y2);
g.drawLine((int)x2,(int)y2,(int)x3,(int)y3); g.drawLine((int)x1,(int)y1,(int)x3,(int)y3);
double tempx1,tempy1,tempx2,tempy2,tempx3,tempy3;
tempx1=(double)((x1+x2)/2);
tempy1=(double)((y1+y2)/2);
tempx2=(double)((x1+x3)/2);
tempy2=(double)((y1+y3)/2);
tempx3=(double)((x3+x2)/2);
tempy3=(double)((y3+y2)/2);
//判断退出条件
if(count>10){return;}
shower(x1,y1,tempx1,tempy1,tempx2,tempy2,g,count);
shower(x2,y2,tempx3,tempy3,tempx1,tempy1,g,count); shower(x3,y3,tempx3,tempy3,tempx2,tempy2,g,count);
}
//重写重绘函数,调用递归函数
public void paint(Graphics g){
super.paint(g);
shower(250,50,50,400,450,400,g,0);
}
}
在编写该程序的过程中,我也遇到了很多问题。
其中最严重的问题就是计数常数count,在我首先编写该程序时,我将计数常数count定义成Digui类的一个属性,作为全局变量,但是,这样就会出现一些问题。例如,如果是这样,那么(此处将count从参数中略去)if(count>10){return;}
shower(x1,y1,tempx1,tempy1,tempx2,tempy2,g);
shower(x2,y2,tempx3,tempy3,tempx1,tempy1,g); shower(x3,y3,tempx3,tempy3,tempx2,tempy2,g);
此句话将只执行shower(x1,y1,tempx1,tempy1,tempx2,tempy2,g,count);中的有效部分,因为在执行完第一个函数后,count将返回10而不是返回0;而如果是作为函数中的参数,则能解决该问题。
[img]http://dl2.iteye.com/upload/attachment/0086/7050/b9bec82a-f8ad-3e6d-aebc-9debd773996a.png[/img]
本次课程是通过递归的方法来实现分形的操作。
递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。(以上参考专业资料)
用自己的话来说,如果实现一个目的,需要调用多次类似的方法,那么,我们就可以用到递归,而递归正确的重要条件是要有退出的条件,否则,递归将很有可能变成死递归,就像循环中的死循环一样。
那么,接下来是实现谢宾斯基三角形的递归方法:
public class Digui extends JFrame{
//private int count=0;
/**Digui类继承JFrame类
* @param args
*/
public static void main(String[] args) {
//实例化一个Digui对象,并设置相关属性
Digui di=new Digui();
di.setTitle("超级三角形");
di.setSize(500,500);
di.setLocationRelativeTo(null);
di.setDefaultCloseOperation(3);
di.setVisible(true);
//获取di对象的画布
Graphics g=di.getGraphics();
}
public void shower(double x1,double y1,double x2,double y2,double x3,double y3,Graphics g,int count){
//计数变量作用
count++;
//划线
g.drawLine((int)x1,(int)y1,(int)x2,(int)y2);
g.drawLine((int)x2,(int)y2,(int)x3,(int)y3); g.drawLine((int)x1,(int)y1,(int)x3,(int)y3);
double tempx1,tempy1,tempx2,tempy2,tempx3,tempy3;
tempx1=(double)((x1+x2)/2);
tempy1=(double)((y1+y2)/2);
tempx2=(double)((x1+x3)/2);
tempy2=(double)((y1+y3)/2);
tempx3=(double)((x3+x2)/2);
tempy3=(double)((y3+y2)/2);
//判断退出条件
if(count>10){return;}
shower(x1,y1,tempx1,tempy1,tempx2,tempy2,g,count);
shower(x2,y2,tempx3,tempy3,tempx1,tempy1,g,count); shower(x3,y3,tempx3,tempy3,tempx2,tempy2,g,count);
}
//重写重绘函数,调用递归函数
public void paint(Graphics g){
super.paint(g);
shower(250,50,50,400,450,400,g,0);
}
}
在编写该程序的过程中,我也遇到了很多问题。
其中最严重的问题就是计数常数count,在我首先编写该程序时,我将计数常数count定义成Digui类的一个属性,作为全局变量,但是,这样就会出现一些问题。例如,如果是这样,那么(此处将count从参数中略去)if(count>10){return;}
shower(x1,y1,tempx1,tempy1,tempx2,tempy2,g);
shower(x2,y2,tempx3,tempy3,tempx1,tempy1,g); shower(x3,y3,tempx3,tempy3,tempx2,tempy2,g);
此句话将只执行shower(x1,y1,tempx1,tempy1,tempx2,tempy2,g,count);中的有效部分,因为在执行完第一个函数后,count将返回10而不是返回0;而如果是作为函数中的参数,则能解决该问题。
[img]http://dl2.iteye.com/upload/attachment/0086/7050/b9bec82a-f8ad-3e6d-aebc-9debd773996a.png[/img]