使用乌龟图形递归Sierpinski地毯

时间:2019-07-21 13:45:56

标签: python recursion turtle-graphics fractals

此问题基于python递归。应该用度= 4来完成,所以有4个不同级别的盒子。我的问题是,使用我已经拥有的代码,在其他学位课程中却表现不佳。请让我知道我做错了什么,下面是我用来获取所有值的代码。

import turtle


def drawboxes(points, color, myTurtle):
    myTurtle.fillcolor(color)
    myTurtle.up()  # Pen up
    myTurtle.goto(points[0][0], points[0][1])
    myTurtle.down()  # Pen down
    myTurtle.begin_fill()
    myTurtle.goto(points[1][0], points[1][1])
    myTurtle.goto(points[2][0], points[2][1])
    myTurtle.goto(points[3][0], points[3][1])
    myTurtle.goto(points[0][0], points[0][1])
    myTurtle.end_fill()

def getMid1(p1, p2):
    return ((p1[0] + p2[0]) / 3, (p1[1] + p2[1]) / 3)

def getMid2(p1, p2):
    return ((p1[0] + p2[0]) / 3 * 2, (p1[1] + p2[1]) / 3 * 2)

def getMid3(p1, p2):
    return ((p1[0] + p2[0]) / 3 * 2, (p1[1] + p2[1]) / 3)

def getMid4(p1, p2):
    return ((p1[0] + p2[0]) / 3, (p1[1] + p2[1]) / 3 * 2)

def getMid5(p1, p2):
    return ((p1[0] + p2[0]) / 3, p1[1] + p2[1])

def getMid6(p1, p2):
    return ((p1[0] + p2[0]) / 3 * 2, (p1[1] + p2[1]))

def getMid7(p1, p2):
    return ((p1[0] + p2[0]), (p1[1] + p2[1]) / 3 * 2)

def getMid8(p1, p2):
    return ((p1[0] + p2[0]), (p1[1] + p2[1]) / 3)

def sierpinski(points, degree, myTurtle):
    colormap = ['blue', 'red', 'green', 'cyan', 'yellow',
                'violet', 'orange']

    drawboxes(points,colormap[degree], myTurtle)

    if degree > 0:
        sierpinski([points[0],
                getMid1(points[0], points[1]),
                getMid1(points[0], points[2]),
                getMid1(points[0], points[3])],
               degree-1, myTurtle)
        sierpinski([getMid1(points[0], points[1]),
                getMid2(points[0], points[1]),
                getMid4(points[0], points[2]),
                getMid1(points[0], points[2])],
               degree-1, myTurtle)
        sierpinski([points[1],
                    getMid2(points[0], points[1]),
                    getMid4(points[1], points[3]),
                    getMid5(points[1], points[3])],
                   degree - 1, myTurtle)
        sierpinski([getMid5(points[1], points[3]),
                    getMid4(points[0], points[2]),
                    getMid2(points[1], points[3]),
                    getMid6(points[1], points[3])],
                   degree - 1, myTurtle)
        sierpinski([getMid2(points[1], points[3]),
                    getMid6(points[1], points[3]),
                    points[2],
                    getMid7(points[1], points[3])],
                   degree - 1, myTurtle)
        sierpinski([getMid3(points[1], points[3]),
                    getMid2(points[1], points[3]),
                    getMid7(points[1], points[3]),
                    getMid8(points[1], points[3])],
                   degree - 1, myTurtle)
        sierpinski([getMid2(points[0], points[3]),
                    getMid3(points[1], points[3]),
                    getMid8(points[1], points[3]),
                    points[3]],
                   degree - 1, myTurtle)
        sierpinski([getMid1(points[0], points[3]),
                    getMid1(points[0], points[2]),
                    getMid3(points[1], points[3]),
                    getMid2(points[0], points[3])],
                   degree - 1, myTurtle)


def main():
    myTurtle = turtle.Turtle()
    myTurtle.speed(10)  # adjust the drawing speed here
    myWin = turtle.Screen()
    # 3 points of the first triangle based on [x,y] coordinates
    myPoints = [[0, 0], [0, 300], [300, 300], [300, 0]]
    degree = 1  # Vary the degree of complexity here
    # first call of the recursive function
    sierpinski(myPoints, degree, myTurtle)

    myTurtle.hideturtle()  # hide the turtle cursor after drawing is
# completed
    myWin.exitonclick()  # Exit program when user click on window


main()

2 个答案:

答案 0 :(得分:0)

某些计算仅在P1为(0,0)时才能正确运行,但在P1不同时会给出错误的结果。

对于getMid1,您有

 X = (A + B)/3

对于A=0, B=3,它给出正确的结果

 X = (0 + 3)/3 = 1          

是A与B之间距离的1/3

但是对于A = 1,B = 2给出

 X = (1 + 2)/3 = 1          

因此它给出了X=A,但正确的值是X=1+(1/3)

正确的结果给出公式

 X = A + ((B - A)/3)

 X = A + (1/3 * (B-A))

相似的公式应该用于其他方面,但我尚未对其进行检查。

 X = A + (0/3 * (B-A)) # = A
 X = A + (1/3 * (B-A)) 
 X = A + (2/3 * (B-A))
 X = A + (3/3 * (B-A)) # = B

编辑:

enter image description here

使用公式创建了工作代码。

但是我将代码简化为一个函数get(),而不是八个getMid1 ... getMid8。它使用VH计算V/3H/30/31/32/33/3

def get(p1, p2, V, H, show=False): # Vertical, Horizontal
    x1, y1 = p1
    x2, y2 = p2

    dx = x2 - x1
    dy = y2 - y1

    new_x = x1 + V/3 * dx
    new_y = y1 + H/3 * dy

    if show:
        print('NEW:', new_x, new_y)

    return new_x, new_y

在计算中,我也只使用points[0], points[2],因为我可以在points[0], points[2]中的points[1], points[3]中找到值

完整代码:

import turtle

def drawTriangle(points, color, myTurtle, show=False):
    if show:
        print('DRAW:', points)

    myTurtle.fillcolor(color)
    myTurtle.up()  # Pen up
    myTurtle.goto(points[0][0], points[0][1])
    myTurtle.down()  # Pen down
    myTurtle.begin_fill()
    myTurtle.goto(points[1][0], points[1][1])
    myTurtle.goto(points[2][0], points[2][1])
    myTurtle.goto(points[3][0], points[3][1])
    myTurtle.goto(points[0][0], points[0][1])
    myTurtle.end_fill()


def get(p1, p2, V, H, show=False): # Vertical, Horizontal
    x1, y1 = p1
    x2, y2 = p2

    dx = x2 - x1
    dy = y2 - y1

    new_x = x1 + V/3 * dx
    new_y = y1 + H/3 * dy

    if show:
        print('NEW:', new_x, new_y)

    return new_x, new_y


def sierpinski(points, degree, myTurtle):

    colormap = ['blue', 'red', 'green', 'cyan', 'yellow',
                'violet', 'orange']

    # Draw a triangle based on the 3 points given
    drawTriangle(points, colormap[degree], myTurtle)

    if degree > 0:
        #print('--- 1 ---')
        #print(points)
        sierpinski([
                get(points[0], points[2], 0, 0),
                get(points[0], points[2], 0, 1),
                get(points[0], points[2], 1, 1),
                get(points[0], points[2], 1, 0)
               ], degree-1, myTurtle)

        #print('--- 2 ---')
        #print(points)
        sierpinski([
                get(points[0], points[2], 0, 1),
                get(points[0], points[2], 0, 2),
                get(points[0], points[2], 1, 2),
                get(points[0], points[2], 1, 1)
               ], degree-1, myTurtle)

        #print('--- 3 ---')
        #print(points)
        sierpinski([
                get(points[0], points[2], 0, 2),
                get(points[0], points[2], 0, 3),
                get(points[0], points[2], 1, 3),
                get(points[0], points[2], 1, 2)
               ], degree-1, myTurtle)

        #print('--- 4 ---')
        #print(points)
        sierpinski([
                get(points[0], points[2], 1, 2),
                get(points[0], points[2], 1, 3),
                get(points[0], points[2], 2, 3),
                get(points[0], points[2], 2, 2)
               ], degree-1, myTurtle)

        #print('--- 5 ---')
        #print(points)
        sierpinski([
                get(points[0], points[2], 2, 2),
                get(points[0], points[2], 2, 3),
                get(points[0], points[2], 3, 3),
                get(points[0], points[2], 3, 2)
               ], degree-1, myTurtle)

        #print('--- 6 ---')
        #print(points)
        sierpinski([
                get(points[0], points[2], 2, 1),
                get(points[0], points[2], 2, 2),
                get(points[0], points[2], 3, 2),
                get(points[0], points[2], 3, 1)
               ], degree-1, myTurtle)

        #print('--- 7 ---')
        #print(points)
        sierpinski([
                get(points[0], points[2], 2, 0),
                get(points[0], points[2], 2, 1),
                get(points[0], points[2], 3, 1),
                get(points[0], points[2], 3, 0)
               ], degree-1, myTurtle)

        #print('--- 8 ---')
        #print(points)
        sierpinski([
                get(points[0], points[2], 1, 0),
                get(points[0], points[2], 1, 1),
                get(points[0], points[2], 2, 1),
                get(points[0], points[2], 2, 0)
               ], degree-1, myTurtle)


def main():
    myTurtle = turtle.Turtle()
    myTurtle.speed(0)  # adjust the drawing speed here
    myWin = turtle.Screen()

    size = 300
    # 3 points of the first triangle based on [x,y] coordinates
    myPoints = [[0, 0], [0, size], [size, size], [size, 0]]

    degree = 3  # Vary the degree of complexity here

    # first call of the recursive function
    sierpinski(myPoints, degree, myTurtle)

    myTurtle.hideturtle()  # hide the turtle cursor after drawing is completed
    myWin.exitonclick()  # Exit program when user click on window


main()

答案 1 :(得分:0)

我为您称呼四个有角的形状“三角形” 而感到困惑。继续:

我相信您的代码的问题在于如何确定每次递归的原点-正如所写的那样,代码返回绝对值(0,0)的频率比应有的要高。为了理解您的代码,我将其拆开并重新组合在一起。但这现在是一种非常不同的野兽。我呼吁乌龟的 <stockinfo> <partner_id>88</partner_id> <export_ts>2016-10-28 06:50:00</export_ts> <item_list> <item> <item_id>123</item_id> <item_ean>123456789012</item_ean> <item_name>Test Item 1</item_name> <brand>Brandname</brand> <weight/> <price_gross>12.00</price_gross> <stock_qty>20</stock_qty> </item> <item> <item_id>456</item_id> <item_ean>4567890123</item_ean> <item_name>Test Item 2</item_name> <brand>Brandname2</brand> <weight/> <price_gross>12.90</price_gross> <stock_qty>4</stock_qty> </item> </item_list> </stockinfo> 整体上处理姿势,而不是分别对它们的X和Y坐标进行操作。我用循环替换了您的八个递归调用块:

Vec2D

enter image description here

我意识到这不是您可以直接合并的代码,但希望其中的一些想法对打印和比较职位很有帮助。

相关问题