使用递归绘制分形
Drawing fractals using recursion
最近我开始学习递归,我注意到有一种叫做分形的东西,我用它做了简单的树。
但是我在获得这个分形的递归思想时遇到了问题https://i.imgur.com/RMPfwU2.png
我看到了类似的东西,但是是用正方形做的。
任何人都可以解释一下这个的递归思想吗?
我用 Python(turtle)
尝试了这个算法
def fractal(start,length,direction,t):
if(length < 10):
return
t.rt(direction)
direction = int(direction/360) # To make it only {90,-90}
t.fd(length)
fractal(start+length,length/2,direction+90,t)
fractal(start+length,length/2,direction-90,t)
t.lt(direction)
fractal(start+length,length/2,direction+90,t)
fractal(start+length,length/2,direction-90,t)
分形的基本形状是一个大字母 "H",在其四个尖端的每个尖端都有较小的自身版本。所以你基本上要做的是在海龟中画一个 "H" ,每当你在提示时,再次调用 fractal
一半的长度。请记住,海龟在函数启动时应始终指向同一方向,并且在绘制形状后必须 return 到原点。该函数可能看起来像这样:
def fractal(length, t):
if length >= 10 :
# draw left side
t.lt(90)
t.fd(length)
t.rt(90)
t.fd(length)
fractal(length//2, t)
t.bk(length*2)
fractal(length//2, t)
t.fd(length)
# draw right side
t.rt(90)
t.fd(length*2)
t.lt(90)
t.fd(length)
fractal(length//2, t)
t.bk(length*2)
fractal(length//2, t)
t.fd(length)
# back to origin
t.lt(90)
t.fd(length)
t.rt(90)
你也可以利用图形两边对称的事实:
def fractal(length, t):
if length >= 10:
t.rt(90)
side(length, t)
t.rt(180)
side(length, t)
t.rt(90)
def side(length, t):
t.fd(length)
t.rt(90)
t.fd(length)
fractal(length//2, t)
t.bk(length*2)
fractal(length//2, t)
t.fd(length)
t.lt(90)
t.bk(length)
不是最快的实现,但它很紧凑,让您猜测下一步的发展方向:
from turtle import Screen, Turtle
def fractal(turtle, length, minimum):
if length < minimum:
return
angle = 90
length //= 2
for _ in range(2):
for _ in range(2):
turtle.forward(length)
turtle.left(angle)
turtle.forward(length)
turtle.left(angle)
fractal(turtle, length, minimum)
turtle.left(angle)
turtle.forward(length)
turtle.right(angle)
turtle.forward(length)
angle = -angle
screen = Screen()
yertle = Turtle()
yertle.speed('fastest') # because I have no patience
fractal(yertle, 100, 10)
screen.exitonclick()
首先画到H的右上角,向内转,递归。完成递归后,我们将继续沿相同方向转动以向下移动到臂下。我们 return 没有一直沿着手臂向下移动(最有效的做法),而是到达我们的起点,但现在我们面对相反的方向,所以我们简单地重复我们到目前为止所做的一切来绘制较低的H 左边
一旦完成,我们又回到了中心指向原来的方向,所以我们再次重复整个过程,但通过取反角度将我们所有的右手变成左手,反之亦然。这将绘制我们的左下腿,然后绘制右上腿。
最近我开始学习递归,我注意到有一种叫做分形的东西,我用它做了简单的树。
但是我在获得这个分形的递归思想时遇到了问题https://i.imgur.com/RMPfwU2.png
我看到了类似的东西,但是是用正方形做的。
任何人都可以解释一下这个的递归思想吗? 我用 Python(turtle)
尝试了这个算法def fractal(start,length,direction,t):
if(length < 10):
return
t.rt(direction)
direction = int(direction/360) # To make it only {90,-90}
t.fd(length)
fractal(start+length,length/2,direction+90,t)
fractal(start+length,length/2,direction-90,t)
t.lt(direction)
fractal(start+length,length/2,direction+90,t)
fractal(start+length,length/2,direction-90,t)
分形的基本形状是一个大字母 "H",在其四个尖端的每个尖端都有较小的自身版本。所以你基本上要做的是在海龟中画一个 "H" ,每当你在提示时,再次调用 fractal
一半的长度。请记住,海龟在函数启动时应始终指向同一方向,并且在绘制形状后必须 return 到原点。该函数可能看起来像这样:
def fractal(length, t):
if length >= 10 :
# draw left side
t.lt(90)
t.fd(length)
t.rt(90)
t.fd(length)
fractal(length//2, t)
t.bk(length*2)
fractal(length//2, t)
t.fd(length)
# draw right side
t.rt(90)
t.fd(length*2)
t.lt(90)
t.fd(length)
fractal(length//2, t)
t.bk(length*2)
fractal(length//2, t)
t.fd(length)
# back to origin
t.lt(90)
t.fd(length)
t.rt(90)
你也可以利用图形两边对称的事实:
def fractal(length, t):
if length >= 10:
t.rt(90)
side(length, t)
t.rt(180)
side(length, t)
t.rt(90)
def side(length, t):
t.fd(length)
t.rt(90)
t.fd(length)
fractal(length//2, t)
t.bk(length*2)
fractal(length//2, t)
t.fd(length)
t.lt(90)
t.bk(length)
不是最快的实现,但它很紧凑,让您猜测下一步的发展方向:
from turtle import Screen, Turtle
def fractal(turtle, length, minimum):
if length < minimum:
return
angle = 90
length //= 2
for _ in range(2):
for _ in range(2):
turtle.forward(length)
turtle.left(angle)
turtle.forward(length)
turtle.left(angle)
fractal(turtle, length, minimum)
turtle.left(angle)
turtle.forward(length)
turtle.right(angle)
turtle.forward(length)
angle = -angle
screen = Screen()
yertle = Turtle()
yertle.speed('fastest') # because I have no patience
fractal(yertle, 100, 10)
screen.exitonclick()
首先画到H的右上角,向内转,递归。完成递归后,我们将继续沿相同方向转动以向下移动到臂下。我们 return 没有一直沿着手臂向下移动(最有效的做法),而是到达我们的起点,但现在我们面对相反的方向,所以我们简单地重复我们到目前为止所做的一切来绘制较低的H 左边
一旦完成,我们又回到了中心指向原来的方向,所以我们再次重复整个过程,但通过取反角度将我们所有的右手变成左手,反之亦然。这将绘制我们的左下腿,然后绘制右上腿。