我试图理解递归函数,它们看起来很复杂。到目前为止,我唯一了解的是,它们需要是一个基本情况,并且是基于归纳证明的。程序员如何看待简单的基本情况是迄今为止无法思考的。示例分形在一本书中仅使用一行基本情况求解。在谢尔平斯基三角形中,我需要很多行代码。好吧,现在我接近它,但仍然遥不可及。下面是适用于订单 0 和 1 的代码,但对于更高的订单,它增加了更多空间。我知道这不是pythonic代码,但这是我能写的最好的代码。
import math, turtle
window=turtle.Screen()
window.title('Sierpinski')
window.bgcolor('lightblue')
alex=turtle.Turtle()
def sierpinski(a,t,size):
if a==0:
for i in range(3):
t.forward(size)
t.left(120)
else:
sierpinski(a-1,t,size/3)
t.forward(size/3)
sierpinski(a-1,t,size/3)
t.forward(size/3)
t.left(120)
t.forward(size/3)
sierpinski(a-1,t,size/3)
t.forward(size/3)
t.left(120)
t.forward(size*2/3)
t.left(120)
sierpinski(3,alex,200)
window.mainloop()
是的,有点长,我的思维过程仍然不清楚
- 谁能解释一下我的代码有什么问题?
- 如何让它变得更有pythonic?
好的,我在视频的帮助下找到了如何做到这一点,它指示我将其分成两半而不是三分之一。
所以代码应该是
import math, turtle
window=turtle.Screen()
window.title('Sierpinski')
window.bgcolor('lightblue')
alex=turtle.Turtle()
def sierpinski(a,t,size):
if a==0:
for i in range(3):
t.forward(size)
t.left(120)
else:
sierpinski(a-1,t,size/2)
t.forward(size/2)
sierpinski(a-1,t,size/2)
t.forward(size/2)
t.left(120)
t.forward(size/2)
sierpinski(a-1,t,size/2)
t.forward(size/2)
t.left(120)
t.forward(size)
t.left(120)
sierpinski(3,alex,200)
window.mainloop()
但是代码可以更简洁吗?
编辑
这就足够了:
def sierpinski(a, t, size):
half = size / 2
if a >= 0:
sierpinski(a-1, t, half)
t.forward(half)
sierpinski(a-1, t, half)
t.forward(half)
t.left(120)
t.forward(half)
sierpinski(a-1, t, half)
t.forward(half)
t.left(120)
t.forward(size)
t.left(120)
这是有效的if
因为块的末端else
都在绘制三角形(else
块只是为了移动光标,但仍然如此(,但else
块进行了递归调用。
为了使它"更pythonic">,你可以把它们全部放到一个类中:
class SierpinskiTurtle(turtle.Turtle):
def sierpinski(self, depth, size):
half = size / 2
if depth >= 0:
self.sierpinski(depth-1, half)
self.forward(half)
self.sierpinski(depth-1, half)
self.forward(half)
self.left(120)
self.forward(half)
self.sierpinski(depth-1, half)
self.forward(half)
self.left(120)
self.forward(size)
self.left(120)
alex = SierpinskiTurtle()
alex.sierpinski(3, 200)
我们可以使用冲压而不是绘图来使sierpinski()
功能更简单、更快捷:
from turtle import Turtle, Screen
CURSOR_SIZE = 20
def sierpinski(depth, turtle, size):
turtle.shapesize(size / CURSOR_SIZE)
turtle.stamp()
if depth < 1:
return
half = size / 2
circumradius = half * 3 ** 0.5 / 3
for _ in range(3):
turtle.forward(circumradius) # to
sierpinski(depth - 1, turtle, half)
turtle.backward(circumradius) # and fro
turtle.left(120)
window = Screen()
window.mode('logo') # make 0 degrees straight up
window.title('Sierpinski')
window.bgcolor('lightblue')
alex = Turtle('triangle')
alex.fillcolor(window.bgcolor())
alex.penup()
sierpinski(3, alex, 300)
alex.hideturtle()
window.mainloop()
这也具有将三角形绘制在屏幕上而不是偏向一侧的优点。 通过让光标围绕三角形的内半径以圆形方式移动,而不是围绕中心来回移动,可以进一步优化绘图。