Python递归函数导致Pygame冻结

时间:2017-01-02 23:27:02

标签: python recursion pygame paint

我在python中有一个非常复杂的模拟绘图程序,大约有350行。然而,当我使用我的填充桶工具时,它填充我绘制的形状,然后冻结Pygame窗口,无论形状的大小。我仍然可以移动鼠标和窗口,标题不会更改为“无响应”。但当我的鼠标悬停在窗口上时,光标会变为旋转轮。

我的填充铲斗工具是一个递归程序,泛滥填充周围的像素,并在颜色不同时停止。

我增加了递归限制,堆栈大小为64 mB。

以下是它的简化版本:

from pygame import *
from sys import *
from math import *
from threading import *

screen = display.set_mode((800,600)) #Same size as my real paint canvas
white = (255,255,255)
red = (255,0,0)
brush = Rect(0,0,25,25)
bucket = Rect(30,0,25,25)
running = True
tool = 1

setrecursionlimit(20000)
stack_size(67108864)
screen.fill(white)
draw.rect(screen,0,(0,0,25,25),0)
draw.rect(screen,0,(30,0,25,25),0)

def fill(x,y,oldColor,newColor,n1,n2,n3,n4):
    if n1 >=800 : #Stops flooding right when it exceeds width
        return
    if n2 <= 0: #Stops flooding left
        return
    if n3 >= 600: #Stops down
        return
    if n4 <= 0: #Stops up
        return
    try:
        if screen.get_at((x,y)) != oldColor:
        return
    except IndexError:
        return
    draw.rect(screen,newColor,(x,y,1,1),0)
    fill(x+1,y,oldColor,newColor,n1=n1+1,n2=n2,n3=n3,n4=n4) #Floods right
    fill(x-1,y,oldColor,newColor,n1=n1,n2=n2-1,n3=n3,n4=n4) #Left
    fill(x,y+1,oldColor,newColor,n1=n1,n2=n2,n3=n3+1,n4=n4) #Down
    fill(x,y-1,oldColor,newColor,n1=n1,n2=n2,n3=n3,n4=n4+1) #Up

while running:
    for e in event.get():
        if e.type == QUIT:
            running = False
    mb = mouse.get_pressed()
    mx,my = mouse.get_pos()
    if brush.collidepoint(mx,my) and mb[0] == 1:
        tool = brush
    if bucket.collidepoint(mx,my) and mb[0] == 1:
        tool = fill
    if tool == brush and mb[0] == 1:
        draw.circle(screen,red,(mx,my),5,0)
    if tool == fill and mb[0] == 1:
        pixel = screen.get_at((mx,my))
        fill(mx,my,pixel,red,mx,mx,my,my)
    display.flip()
quit()

任何人都知道为什么Pygame在填充形状后会冻结?

1 个答案:

答案 0 :(得分:1)

Your typo with regard to n4 (n4 = n4 + 1) doesn't properly bounds check going off the top of the screen. Your rectangle that you're drawing and presumably clicking on to test this touches the top of the screen. It recurses upwards forever.

I also made some other comments above on how to clean this up significantly.