【问题标题】:Improving Chaos Game efficiency提高混沌游戏效率
【发布时间】:2019-09-25 15:28:21
【问题描述】:

我编写了这个脚本来使用海龟模块来复制我在 Numberphile 频道上看到的混沌游戏。绘制了大量的点以使其在更大的范围内实际运行良好。我认为大量的点是导致程序在一段时间后开始运行变慢的原因,我想知道是否有人可以帮助我想出一个解决方法。

我愿意接受任何类型的解决方案,只要控件保持不变并且顶点数可以是 3 以上的任意数字。

如果有人不知道混沌游戏是什么,那就是一个包含任意数量顶点的多边形的游戏。首先,您在多边形内放置一个点,随机选择一个顶点并在您刚刚放置的点和随机选择的顶点之间的中间绘制一个新点。你不断重复这个过程,每次你都会使用新绘制的点。

在这个脚本中,我还包含了一条规则,以确保它不会连续两次选择相同的顶点来形成具有超过 3 个顶点的漂亮分形。 3 个顶点实际上形成了谢尔宾斯基三角形。

这里是 Numberphile 视频的链接:https://www.youtube.com/watch?v=kbKtFN71Lfs

您可能会说,我对 Python 和一般编码有点陌生。

完整代码:

import turtle as t
import tkinter as tk
from tkinter import ttk
from random import randint
wn = t.Screen()
wn.colormode(255)
t.pu();t.ht();t.speed(0)
plist = []

l = 0
val = 0

pb=ttk.Progressbar(orient="horizontal",length=wn.window_width(),mode="determinate")
pb.pack(side=tk.BOTTOM)
pb["value"]=0

def Clear():
    t.clear()
    plist = []
def Dot(x, y):
    t.goto(x, y)
    t.dot(5, (0, 0, 255))
    plist.append(t.pos())
def Run(x, y):
    wn.onscreenclick(None)
    wn.tracer(0, 0)
    l = len(plist)
    pb["maximum"]=l*1000
    xyc = randint(0, l-1)
    xyc_old = 0
    for _ in range(l*10):
        xyc = randint(0, l-1)
        for i in range(100):
            xyc = randint(0, l-1);
            if l >= 4:
                while xyc == xyc_old:
                    xyc = randint(0, l-1);
                xyc_old = xyc;
            t.goto((t.pos()[0]+plist[xyc][0])/2, (t.pos()[1]+plist[xyc][1])/2);     
            t.dot(2, (255, 0, 0));
            pb["value"]+=1;
            pb.update()
        wn.update()
    plist.clear()
    wn.onscreenclick(Dot, btn=1)
    wn.onscreenclick(Run, btn=3)  
wn.onscreenclick(Dot, btn=1)
wn.onscreenclick(Run, btn=3)
wn.onkey(Clear, "c")
wn.listen()
wn.mainloop()

我觉得我的编码风格与这里的许多人非常不同,但我希望这不是问题。

谢谢!

【问题讨论】:

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


    【解决方案1】:

    我假设大量的点是程序开始的原因 稍微慢了一点,我想知道是否有人可以帮助我 想出一个解决方法。

    令人惊讶的是,没有。这是您自己的仪器(进度条)减慢您的速度。注释掉:

    pb.update()
    

    看看会发生什么。

    我觉得我的编码风格与很多人非常不同 在这里,但我希望这不是问题。

    这是一个与 bad 编码风格重叠的问题。例如。缺少空格、使用分号、代码中的有效无操作等。我对您的代码的返工:

    from turtle import Screen, Turtle
    import tkinter as tk
    from tkinter import ttk
    from random import randrange
    
    def clear():
        turtle.clear()
        plist.clear()
    
    def dot(x, y):
        turtle.goto(x, y)
        turtle.dot(5, 'blue')
        plist.append(turtle.position())
    
    def run(x, y):
        screen.onscreenclick(None, btn=1)
        screen.onscreenclick(None, btn=3)
        screen.onkey(None, 'c')
    
        length = len(plist)
        flag = length >= 4
        pb['maximum'] = length * 1000
        xyc_old = 0
    
        for _ in range(length * 100):
            for _ in range(10):
                xyc = randrange(length)
    
                if flag:
                    while xyc == xyc_old:
                        xyc = randrange(length)
                    xyc_old = xyc
    
                x, y = turtle.position()
                dx, dy = plist[xyc]
                turtle.goto((x + dx) / 2, (y + dy) / 2)
                turtle.dot(2)
    
            pb['value'] += 10
            pb.update()
    
        plist.clear()
        pb['value'] = 0
    
        screen.onscreenclick(dot, btn=1)
        screen.onscreenclick(run, btn=3)
        screen.onkey(clear, 'c')
    
    plist = []
    
    screen = Screen()
    screen.tracer(False)
    
    turtle = Turtle()
    turtle.hideturtle()
    turtle.setundobuffer(None)
    turtle.color('red')
    turtle.penup()
    
    pb = ttk.Progressbar(orient='horizontal', length=screen.window_width(), mode='determinate')
    pb.pack(side=tk.BOTTOM)
    pb['value'] = 0
    
    screen.onscreenclick(dot, btn=1)
    screen.onscreenclick(run, btn=3)
    screen.onkey(clear, 'c')
    screen.listen()
    
    screen.mainloop()
    

    其他变化包括:

    如果没有global plistClear() 中的plist = [] 将无法工作。请改用plist.clear()

    您还需要在Run 期间禁用(并重新启用)wn.onkey(Clear, "c"),否则您的用户可能会破坏程序。您还需要单独禁用两个鼠标按钮。

    你真的想要randrange(),而不是randint()

    【讨论】:

    • 嗯,我刚刚在发布这个问题的那天添加了进度条。之前也出现过类似的性能问题,但不知何故,这似乎已经快得多了。我想知道这里的大部分工作是否可能是兰德兰奇?我相信当我使用 exec() 来执行实际执行绘图的块时,这些分号就留在了那里。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-13
    • 1970-01-01
    • 2021-04-18
    相关资源
    最近更新 更多