【问题标题】:Having trouble making the Sierpinski Carpet using recursion only and python turtle仅使用递归和 python 龟制作谢尔宾斯基地毯时遇到问题
【发布时间】:2020-12-03 01:21:40
【问题描述】:
import turtle

window = turtle.Screen()
window.screensize(1920,1080)
window.setup(width=1.0, height=1.0, startx=None, starty=None)

# T is a global variable 
T = turtle.Turtle()
T.shape('turtle')
T.speed(2)

def forward_and_rotate(distance, degree, t):
  t.forward(distance)
  t.left(degree)



def draw_square_recursion(distance, t, sides_left=4):
  t.pendown()
  if sides_left == 0:
    return
  else:
    forward_and_rotate(distance, 90, t)

    draw_square_recursion(distance, t, sides_left-1)
  t.penup()


def draw_filled_square(t, side_len, color='black'):
  current_color = T.pencolor()
  t.pendown()
  t.color(color)
  t.begin_fill()
  draw_square_recursion(side_len, t, 4)
  t.end_fill()
  t.penup()
  T.color(current_color)

# Starter code
def sier_carp(t, l, n):
  if n == 0:
    home = t.pos()
    t.goto(home + (l/3, l/3))
    draw_filled_square(t, l/3)
    t.goto(home)
  else:
      sier_carp(t, l/3, n - 1)
      t.fd(l/3)
      sier_carp(t, l/3, n -1)
      t.fd(l/3)
      sier_carp(t, l/3, n -1)
      t.fd(l/3)

      t.left(90)
      t.fd(l/3)

      sier_carp(t, l/3, n - 1)
      t.fd(l/3)
      sier_carp(t, l/3, n -1)
      t.fd(l/3)
      
      t.left(90)
      t.fd(l/3)

      sier_carp(t, l/3, n - 1)
      t.fd(l/3)
      sier_carp(t, l/3, n -1)
      t.fd(l/3)
      
      t.left(90)
      t.fd(l/3)

      sier_carp(t, l/3, n - 1)
      t.fd(l/3)
      sier_carp(t, l/3, n -1)
      t.fd(l/3)
      
      t.left(90)
      t.fd(l/3)

 

    # add more cases!


T.penup()
sl = 200
draw_square_recursion(sl, T, 4)
sier_carp(T, sl, 1)

我很难仅使用递归而不使用循环来绘制谢尔宾斯基地毯。然而,在前三个方格被绘制后,我尝试向左旋转并在巢址上制作接下来的 2 个方格,这些方格偏离了线。如果你愿意,你可以试试这段代码,看看它是什么样子的。顺便说一句,颜色与周围的白色和内部的黑色相反,而不是通常的黑色周围和白色正方形的地毯版本。

【问题讨论】:

    标签: python python-3.x recursion turtle-graphics fractals


    【解决方案1】:

    我将为您的代码做一个简化版本——虽然重复,但您的起始代码确实实现了您的递归目标。但是,我将使用 stamping 而不是 drawing,因此我们可以专注于递归图像,而不是使用海龟绘制正方形的机制:

    from turtle import Screen, Turtle
    
    SIDE_LENGTH = 200
    CURSOR_SIZE = 20
    
    def draw_filled_square(t, side_len):
        t.shapesize(side_len / CURSOR_SIZE)
        t.stamp()
    
    def sier_carp(t, l, n):
        draw_filled_square(t, l)
        
        if n < 1:
            return
    
        x, y = t.position()
    
        t.setx(x + l)
        sier_carp(t, l/3, n - 1)
    
        t.sety(y + l)
        sier_carp(t, l/3, n - 1)
    
        t.setx(x)
        sier_carp(t, l/3, n - 1)
    
        t.setx(x - l)
        sier_carp(t, l/3, n - 1)
    
        t.sety(y)
        sier_carp(t, l/3, n - 1)
    
        t.sety(y - l)
        sier_carp(t, l/3, n - 1)
    
        t.setx(x)
        sier_carp(t, l/3, n - 1)
    
        t.setx(x + l)
        sier_carp(t, l/3, n - 1)
    
        t.goto(x, y)
    
    screen = Screen()
    screen.setup(width=1.0, height=1.0)
    
    turtle = Turtle()
    turtle.hideturtle()
    turtle.shape('square')
    turtle.penup()
    
    sier_carp(turtle, SIDE_LENGTH, 4)
    
    screen.exitonclick()
    

    我故意避免使用screen.tracer(False) 加快速度,因为您应该看到它是如何以逆时针模式绘制的。

    我相信问题比你做的要简单。在这种绘图中,递归函数将海龟返回到函数启动时的位置是很重要的。这允许调用者对其位置做出有效的假设。

    【讨论】:

      【解决方案2】:

      以下是我在开始之前注意到的概念:

      1. 定义一个接受坐标和正方形大小的函数,并返回周围的 8 个坐标。

      2. 定义一个接受坐标和正方形大小的函数,以给定的大小为长度,以给定的坐标为中心点绘制一个正方形。

      3. 定义将接受坐标、大小和递归次数的主函数。坐标将是谢尔宾斯基地毯的中心,尺寸将是完成的谢尔宾斯基地毯的尺寸。


      记住以上几点,让我们开始构建我们的程序:

      1. 导入turtle模块,关闭跟踪器(可选)提高效率并隐藏海龟光标:
      import turtle
      
      turtle.tracer(0)
      turtle.hideturtle()
      
      1. 定义接受坐标和单位的函数,并返回给定坐标周围所有 8 个坐标的列表:
      def surrounding(cor, size):
          x, y = cor
          return [(x - size, y + size),
                  (x + size, y + size),
                  (x - size, y - size),
                  (x + size, y - size),
                  (x - size, y),
                  (x + size, y),
                  (x, y + size),
                  (x, y - size)]
      
      1. 定义一个递归函数,它将接受坐标、大小和计数。它将绘制一个正方形,其中心位于给定坐标处,其尺寸为给定尺寸的三分之一,因此成品地毯的侧面最终将达到给定尺寸。计数用于告诉函数何时停止递归;当计数达到0:
      def draw_square(cor, size, count):
          size /= 3
          count -= 1
          turtle.penup()
          turtle.goto(cor[0] - size / 2, cor[1] + size / 2)
          turtle.pendown()
          turtle.begin_fill()
          turtle.forward(size)
          turtle.right(90)
          turtle.forward(size)
          turtle.right(90)
          turtle.forward(size)
          turtle.right(90)
          turtle.forward(size)
          turtle.right(90)
          turtle.end_fill()
          if count:
              func(surrounding(cor, size), size, count)
      
      1. 定义一个接受坐标和大小的递归函数。它将使用前面定义的surroundings 函数将该坐标转换为环绕坐标列表。然后,它将使用前面定义的draw_square 函数在每个周围坐标处绘制一个正方形:
      def func(cors, size, count):
          if len(cors) == 2:
              draw_square(cors, size, count)
          else:
              draw_square(cors[0], size, count)
              draw_square(cors[1], size, count)
              draw_square(cors[2], size, count)
              draw_square(cors[3], size, count)
              draw_square(cors[4], size, count)
              draw_square(cors[5], size, count)
              draw_square(cors[6], size, count)
              draw_square(cors[7], size, count)
      
      1. 最后,调用主函数func,并更新turtle屏幕(如果跟踪器设置为0
      func((0, 0), 600, 5)
      turtle.update()
      

      总共:

      import turtle
      
      turtle.tracer(0)
      turtle.hideturtle()
      
      def surrounding(cor, size):
          x, y = cor
          return [(x - size, y + size),
                  (x + size, y + size),
                  (x - size, y - size),
                  (x + size, y - size),
                  (x - size, y),
                  (x + size, y),
                  (x, y + size),
                  (x, y - size)]
      
      def draw_square(cor, size, count):
          size /= 3
          count -= 1
          turtle.penup()
          turtle.goto(cor[0] - size / 2, cor[1] + size / 2)
          turtle.pendown()
          turtle.begin_fill()
          turtle.forward(size)
          turtle.right(90)
          turtle.forward(size)
          turtle.right(90)
          turtle.forward(size)
          turtle.right(90)
          turtle.forward(size)
          turtle.right(90)
          turtle.end_fill()
          if count:
              func(surrounding(cor, size), size, count)
      
      def func(cors, size, count):
          if len(cors) == 2:
              draw_square(cors, size, count)
          else:
              draw_square(cors[0], size, count)
              draw_square(cors[1], size, count)
              draw_square(cors[2], size, count)
              draw_square(cors[3], size, count)
              draw_square(cors[4], size, count)
              draw_square(cors[5], size, count)
              draw_square(cors[6], size, count)
              draw_square(cors[7], size, count)
      
      func((0, 0), 600, 5)
      turtle.update()
      

      输出:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-05-30
        • 2018-03-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多