0

私は現在、ヒルベルト曲線のn番目の反復をGUIで入力できる小さなプロジェクトに取り組んでおり、曲線はタートルで描画され、同じウィンドウに表示されます(新しいウィンドウは開きません)。正常に動作しているように見える計算ボタンと、画面をクリアしてタートルを初期状態にリセットする再起動ボタンがあります。これは現在、n の計算プロセスが終了し、描画も終了している場合にのみ機能します。したがって、タートルがまだ描画しているときに関数/プロセスをリセットしようとすると、おかしくなります。clear 関数を再定義する必要があるか、非常に簡単なものを見落としているようです。プロセス(メイン)が未完成の場合は、これを実行するなど、条件ステートメントを実行する必要があると思います。私はそれを思いつくことができず、助けを願っています。

これがコードです(ドイツ語がそれを理解するのを妨げないことを願っています):

""" Projektabgabe Python """

import turtle
import tkinter as tk
from tkinter import messagebox


""" Fenster-Deklaration und Umgebung """
window = tk.Tk()
window.title("Hilbert-Kurve")
window.geometry("600x600")

canvas = tk.Canvas(master=window, width=500, height=500)
canvas.pack()
""" RawTurtle um Turtle mit Tkinter zu verbinden """
s = turtle.TurtleScreen(canvas)
t = turtle.RawTurtle(canvas) 

""" Eingabefeld für Benutzereingabe """
eingabe_n = tk.Entry(window)
eingabe_n.pack()

""" Funktion der Hilbert-Kurve """
def hilbert(n, angle, step):
    """ Diese Funktion berechnet rekursiv die Hilbert-Kurve der n-ten Iterationsstufe.
        n: n-te Iterationsstufe der Hilbert-Kurve
        angle: der Winkel der Abzweigung, in main wird diese nach Definition der "Kurve" auf 90 gesetzt.
        step: bezeichnet Schrittlänge (in Pixel) die Turtle nach geg. n hinterlegt.
        Ausgabe: Hilbert-Kurve der n-ten Iterationsstufe. """

    # Wenn Höhe 0, gebe nichts zurück
    if n == 0:
        return None
    # Turtle dreht sich nach links um 90 Grad
    t.left(angle)
    hilbert(n-1, -angle, step) 

    t.forward(step)
    
    t.right(angle)
    
    hilbert(n-1, angle, step) 

    t.forward(step) 
    hilbert(n-1, angle, step) 
    t.right(angle)
    t.forward(step)
    
    hilbert(n-1, -angle, step)
    t.left(angle) 

""" Main-Funktion zur Ausgabe der Benutzereingabe
    In diesem Beispiel wurde die Skalierung der Kurve auf size = 250 gesetzt. """  
def main():
    # Wenn nichts in Eingabebox eingegeben, Fehlermeldung bzw. Infobox

    if len(eingabe_n.get())==0:
        messagebox.showinfo(title=None, message="Geben Sie eine natürliche Zahl größer 0 ein.")     

    n = int(eingabe_n.get())
    
    if n > 3:
        t.speed("fastest")
    # Wenn Eingabe 0, Fehlermeldung bzw. Infobox
    if n == 0:
         messagebox.showinfo(title=None, message="Geben Sie eine natürliche Zahl größer 0 ein.")
         t.reset()
    # size bezeichnet die Skalierung der abzubildenen Hilbertkurve     
    size = 400
    t.penup() # Bewege Turtle ohne zu zeichnen
    # Koordinaten (x,y) je nach size berechnen 
    t.goto(-size / 2, -size / 2) # x = -400/2 und y = -400/2
    # Absetzen von Turtle, da Position gefunden
    t.pendown() 
    """ Wenn man in der Hilbert-Kurve ein Segment |_| hat, dann ist dessen Kantenlänge aller drei Kanten die stepsize und am
        Anfang ist die 1 wenn wir den Kasten auf 1 normieren (oder 400 wenn size=400). Dann unterteilt man das Segment ja
        in ein Raster mit 4x4 Punkten, zwischen denen man die neuen Linien zieht. Im Endeffekt die Anzahl der Punkte in dem
        Gitter auf der gesamten Kantenlänge in jedem Schritt verdoppelt, daher ist die Anzahl der Gitterpunkte auf Level n
        dann 2ⁿ. Wenn man zwei nebeneinander liegende Gitterpunkte verbindet (weil sie verschmelzen), kommt man auf 2^n-1 Verbindungslinien.
        Also teilt man die Gesamtstrecke durch 2^n-1 und skaliert das ganze auf die Seitenlänge des Fensters, also
        gerade: size/ 2**n-1. """
    hilbert(n, 90, size/(2 ** n-1))
    
""" Reset-Funktion """
def clearFunc():
    s.clearscreen()
    u = turtle.RawTurtle(canvas)
    t = u
    
""" Button-Deklarierung
    button_n: Bezeichner für den Berechnen Button
    reset_button: Bezeichner für den Reset (zurücksetzen) Button """
button_n = tk.Button(window, text="Berechnen",command=main)
button_n.pack()

reset_button = tk.Button(window, text="Reset", command=clearFunc)
reset_button.pack()

""" Fenster Funktion """
window.mainloop()

4

1 に答える 1

0

あなたの問題は、ヒルベルトが再帰的であり、n==0 で最後に到達するまでそれを止めるものが何もないことです。これを回避するために私が見つけた唯一の方法は次のとおりです。停止したい情報を運ぶ Flag という名前のグローバルブール変数を定義します。

私の提案には3つの変更が含まれており、次のようになります。

「main()」セクションで:

def main():
    global Flag; Flag=False

「hilbert(...)」セクションで:

# Wenn Höhe 0, gebe nichts zurück
if Flag or n == 0:   
    return None

そして最後に、「clearFunc()」セクションで:

def clearFunc():
    global Flag; Flag=True  

私はこれらの 3 つの変更を行い、問題を解決しました (私が理解しているように)。この補助変数のグローバルな性質が不可欠であることに注意してください。

于 2020-09-30T18:27:43.303 に答える