【问题标题】:Sierpinski triangle recursion using turtle graphics使用海龟图形的谢尔宾斯基三角形递归
【发布时间】:2014-11-04 12:50:33
【问题描述】:

我正在尝试编写一个程序,该程序使用海龟用 python 绘制谢尔宾斯基树。这是我的想法:

import turtle
def draw_sierpinski(length,depth):
    window = turtle.Screen()
    t = turtle.Turtle()
    if depth==0:
        for i in range(0,3):
            t.fd(length)
            t.left(120)
    else:
        draw_sierpinski(length/2,depth-1)
        t.fd(length/2)
        draw_sierpinski(length/2,depth-1)
        t.bk(length/2)
        t.left(60)
        t.fd(length/2)
        t.right(60)
        draw_sierpinski(length/2,depth-1)
    window.exitonclick()


draw_sierpinski(500,1)

程序没有到达 else 语句后的第二行,我不知道为什么。谁能帮帮我?

【问题讨论】:

    标签: python recursion turtle-graphics


    【解决方案1】:

    我认为您不应该在函数内创建海龟或窗口对象。因为draw_sierpinski 被调用了四次,如果你最初用深度 1 调用它,那么你将创建四个带有四个独立海龟的独立窗口,每个窗口只绘制一个三角形。相反,我认为你应该只有一扇窗和一只乌龟。

    import turtle
    def draw_sierpinski(length,depth):
        if depth==0:
            for i in range(0,3):
                t.fd(length)
                t.left(120)
        else:
            draw_sierpinski(length/2,depth-1)
            t.fd(length/2)
            draw_sierpinski(length/2,depth-1)
            t.bk(length/2)
            t.left(60)
            t.fd(length/2)
            t.right(60)
            draw_sierpinski(length/2,depth-1)
    
    
    window = turtle.Screen()
    t = turtle.Turtle()
    draw_sierpinski(500,1)
    window.exitonclick()
    

    结果:


    对于深度为 1 的三角形,这些结果看起来相当不错,但是当我们调用 draw_sierpinski(100,2) 时呢?

    哦,不太好。这是因为函数应该绘制形状,然后将海龟返回到其原始起始位置和角度。但是从深度 1 的图像中可以明显看出,乌龟并没有回到它的起始位置。它最终在左坡的一半处结束。您需要一些额外的逻辑才能将其发送回家。

    import turtle
    def draw_sierpinski(length,depth):
        if depth==0:
            for i in range(0,3):
                t.fd(length)
                t.left(120)
        else:
            draw_sierpinski(length/2,depth-1)
            t.fd(length/2)
            draw_sierpinski(length/2,depth-1)
            t.bk(length/2)
            t.left(60)
            t.fd(length/2)
            t.right(60)
            draw_sierpinski(length/2,depth-1)
            t.left(60)
            t.bk(length/2)
            t.right(60)
    
    window = turtle.Screen()
    t = turtle.Turtle()
    draw_sierpinski(100,2)
    window.exitonclick()
    

    结果:

    【讨论】:

    • 谢谢。我对难以解决的解决方案有点困惑......似乎该函数只是使用 t 但我们没有将它作为参数提供给函数。这不是很奇怪吗?
    • t 在这种情况下实际上是一个全局变量。它应该对文件中创建的任何函数可见。
    【解决方案2】:
    # PEP8 Verified
    '''
    The Sierpinski function relies heavily on the getMid function. getMid takes
    as arguments two endpoints and returns the point halfway between them. In
    addition, this program has a function that draws a filled triangle using
    the begin_fill and end_fill turtle methods.
    '''
    
    
    import turtle
    
    
    def drawTriangle(points, color, myTurtle):
        myTurtle.fillcolor(color)
        myTurtle.up()
        myTurtle.goto(points[0][0], points[0][1])
        myTurtle.down()
        myTurtle.begin_fill()
        myTurtle.goto(points[1][0], points[1][1])
        myTurtle.goto(points[2][0], points[2][1])
        myTurtle.goto(points[0][0], points[0][1])
        myTurtle.end_fill()
    
    
    def getMid(p1, p2):
        return ((p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2)
    
    
    def sierpinski(points, degree, myTurtle):
        colormap = ['blue', 'red', 'green', 'white', 'yellow', 'violet', 'orange']
        drawTriangle(points, colormap[degree], myTurtle)
        if degree > 0:
            sierpinski([points[0],
                        getMid(points[0], points[1]),
                        getMid(points[0], points[2])],
                       degree-1, myTurtle)
            sierpinski([points[1],
                        getMid(points[0], points[1]),
                        getMid(points[1], points[2])],
                       degree-1, myTurtle)
            sierpinski([points[2],
                        getMid(points[2], points[1]),
                        getMid(points[0], points[2])],
                       degree-1, myTurtle)
    
    
    def main():
        myTurtle = turtle.Turtle()
        myWin = turtle.Screen()
        myPoints = [[-100, -50], [0, 100], [100, -50]]
        sierpinski(myPoints, 3, myTurtle)
        myWin.exitonclick()
    
    main()
    

    【讨论】:

      【解决方案3】:

      给你。

      import turtle
      
      def sier(side, level):
          if level == 1:
              for i in range(3):
                  turtle.fd(side)
                  turtle.left(120)
          else:
              sier(side/2, level-1)
              turtle.fd(side/2)
              sier(side/2, level-1)
              turtle.bk(side/2)
              turtle.left(60)
              turtle.fd(side/2)
              turtle.right(60)
              sier(side/2, level-1)
              turtle.left(60)
              turtle.bk(side/2)
              turtle.right(60)
      def main():
          sier(200, 4)
      
      if __name__ == '__main__':
          main()
          turtle.mainloop()
      

      【讨论】:

        【解决方案4】:

        这是谢尔宾斯基三角形的最佳代码

        def sierpinski(a, n):
        if n == 0:
            t.begin_fill()
            for i in range(3):
                t.fd(a)
                t.lt(120)
            t.end_fill()
            return
        sierpinski(a / 2, n - 1)
        t.pu()
        t.fd(a / 2)
        t.pd()
        sierpinski(a / 2, n - 1)
        t.pu()
        t.lt(120)
        t.fd(a / 2)
        t.rt(120)
        t.pd()
        sierpinski(a / 2, n - 1)
        #
        # We should return home! This is important!
        #
        t.pu()
        t.lt(60)
        t.bk(a / 2)
        t.rt(60)
        t.pd()
        

        【讨论】:

          【解决方案5】:
          from turtle import *
          import turtle
          t = turtle.Turtle()
          Window = turtle.Screen()
          
          Window.bgcolor('white')
          
          turtle.color('white')
          goto(-200, -200)
          def serp_tri(side, level):
              if level == 1:
                  for i in range(3):
                      turtle.color('black')
                      turtle.ht()
                      turtle.fd(side)
                      turtle.left(120)
                      turtle.speed(100000)
          
          else:
              turtle.ht()
              serp_tri(side/2, level-1)
              turtle.fd(side/2)
              serp_tri(side/2, level-1)
              turtle.bk(side/2)
              turtle.left(60)
              turtle.fd(side/2)
              turtle.right(60)
              serp_tri(side/2, level-1)
              turtle.left(60)
              turtle.bk(side/2)
              turtle.right(60)
              turtle.speed(100000)
          
          def main():
              serp_tri(400, 8)
          
          if __name__ == '__main__':
              main()
              turtle.mainloop()
          

          我查看了一个类似的程序,并使用一些相同的东西编写了这个程序。这将为您提供最大的三角形。希望这可以帮助!

          【讨论】:

            【解决方案6】:

            作为建议,这是我的解决方案。任何 cmets 都非常受欢迎,因为它似乎仍然不是最有效的算法。

            import turtle
            
            def sier(tur, order, size):
                """ Draw Sierpinski triangle """
                if order == 0:
                    for _ in range(3):
                        tur.forward(size)
                        tur.left(120)
                else:
                    step = size / 2
                    for t1, m1, t2, m2 in [(0, step, 0, 0),
                                           (120, step, -120, 0),
                                           (-60, step, 60, -(step))]:
                        sier(tur, order - 1, step)
                        tur.left(t1)
                        tur.forward(m1)
                        tur.left(t2)
                        tur.forward(m2)
            
            
            if __name__ == '__main__':
                odr = int(input("Enter the order: "))
                sz = int(input("Enter the size: "))
            
                root = turtle.Screen()
                root.bgcolor("lightgreen")
            
                alex = turtle.Turtle()
                alex.color('blue')
                alex.speed(100)
            
                sier(alex, odr, sz)
            
                root.mainloop()
            

            【讨论】:

              【解决方案7】:

              从 Navneet Sinha 开始,我建议这样做:

              def sierpinski(t,order,size):
              try:
                  order=int(order)
                  size=float(size)
                  if order==0:
                      for i in range(0,3):
                          t.pendown()             
                          t.forward(size)         
                          t.left(120)
                          t.penup()               
                  else:
                      for (angle,move) in ([0,size],[60,-size],[-60,-size]):
                          sierpinski(t,order-1,size/2)       
                          t.right(angle)                              
                          t.forward(move/2)                           
                          t.left(angle)
              except ValueError:
                  None
              
              def test_turtle():
                  import turtle
              
                  screen=turtle.Canvas()
                  tess=turtle.Turtle()
                  tess.shape("arrow")
                  tess.shapesize(0.2)
                  tess.speed(0)
              
                  ords=input("define the order of the fractal: ")
                  sz=input("define the size of the segment: ")
              
                  tess.penup()
                  tess.backward(float(sz)/2)
                  tess.right(90)
                  tess.forward(float(sz)/3)
                  tess.left(90)
                  tess.pendown()
              
                  sierpinski(tess,ords,sz)
              
                  screen.mainloop()
              
              test_turtle()    
              

              【讨论】:

                【解决方案8】:

                代码真的很简单:

                def sierpinski(size:int,depth:int,up:bool = True):
                    if depth==0:
                        t.forward(size)
                        return
                    size = size/2
                    depth = depth-1
                    left = lambda deg:t.left(deg)
                    right = lambda deg:t.right(deg)
                    if not up:
                        k = left
                        left = right
                        right = k
                        del k
                    left(60)
                    sierpinski(size,depth,not up)
                    right(60)
                    sierpinski(size,depth,up)
                    right(60)
                    sierpinski(size,depth,not up)
                    left(60)
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-10-24
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多