2017-01-02 1 views
0

J'ai un programme de simulation de maquette en python très complexe d'environ 350 lignes. Cependant, lorsque j'utilise mon outil de remplissage, il remplit la forme que j'ai dessinée puis gèle la fenêtre Pygame, quelle que soit la taille de la forme. Je peux toujours déplacer la souris et la fenêtre, et le titre ne change pas pour "Ne répond pas". Mais quand ma souris survole la fenêtre, le curseur se transforme en roue tournante.La fonction de récursion de Python provoque le blocage de Pygame

Mon outil de remplissage de seau est un programme de récursion dont l'inondation remplit les pixels environnants et s'arrête lorsque la couleur est différente.

J'ai augmenté la limite de récursivité et la taille de la pile est de 64 mB.

Voici une version simplifiée de celui-ci:

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() 

Quelqu'un sait pourquoi Pygame gèle après que je remplirai une forme?

+0

De nombreuses (plus?) Utilisations de la récursivité peuvent être remplacées par une boucle. La logique est seulement légèrement différente, mais il n'y a aucun danger de (gasp!) StackOverflow! :-) –

+0

Oui, mais IDLE ne me donne jamais une erreur de limite de récursivité max – WARMFREEZER

+1

OK, donc il est 23 heures, savez-vous où * votre code * est? Imprimez/consignez les entrées dans cette routine. Exécutez une autre méthode de profilage. Exécutez-le dans 'pdb' et appuyez sur^C quand il ne répond plus. Peut-être que ce n'est même pas dans le code que vous pensez qu'il est quand il se bloque. Le débogage est l'une des compétences les plus importantes et les moins enseignées en programmation. Tout le monde peut écrire un programme, mais presque personne ne peut obtenir son programme correctement * la toute première fois. * Source: moi, ca. 1983, quand j'ai commencé à vendre le premier débogueur C * source * au niveau source dans le monde UNIX. –

Répondre

1

Votre faute de frappe concernant n4 (n4 = n4 + 1) ne vérifie pas correctement les limites en haut de l'écran. Votre rectangle que vous dessinez et en cliquant sur probablement pour tester cela touche le haut de l'écran. Il récursive vers le haut pour toujours.

J'ai également fait d'autres commentaires ci-dessus sur la façon de nettoyer cela de manière significative.