[python] (debutant) besoin d'un coup de main

besoin d'un coup de main [python] (debutant) - Python - Programmation

Marsh Posté le 26-08-2007 à 23:45:44    

tout d'abbord bonjour et merci de vous interressez a mon probleme:
 
pour m'entrainer a programer je realise en ce moment un petit projet python, un jeu de gestion en Tkinter. pour la construction des batiment entre les tours j'utilise la fonction suivante:
 
def consTour (self):
        a=0
        if len(self.construcList) !=0:
            while a < len(self.construcList):
                self.construcList[a][0] = self.construcList[a][0]-1
                if self.construcList[a][0]==0:
                    self.consSelecteur(self.construcList[a][1])
                a=a+1

 
self.construcList est la liste ou je stock les ordres de construction de la facons suivante: [1,"farm"] le chiffre au debut indique le nombre de tour restant avant la construction, le second membre me sert d'argument pour ma fonction self.consSelecteur() qui efectue les changement necessaire (dans l'exemple, il ajoute une ferme au possession du joueur).mon probleme est le suivant:
 
quand je lance la construction d'une ferme (la seule possible pour l'instant) pas de probleme, mais quand j'en lance deux en meme temps il ne m'en construit qu'une. aprés quelque recherche j'identifie la ligne qui cause probleme de la maniere suivante:

if len(self.construcList) !=0:
            while a < len(self.construcList):
                print self.construcList
                self.construcList[a][0] = self.construcList[a][0]-1
                print self.construcList
                if self.construcList[a][0]==0:
                    self.consSelecteur(self.construcList[a][1])
                a=a+1

 
ce qui me donnent les lignes suivante:
 
[[1, 'farm'], [1, 'farm']]
[[0, 'farm'], [0, 'farm']]
[[0, 'farm'], [0, 'farm']]
[[-1, 'farm'], [-1, 'farm']]
 
le probleme est donc que le programe me modifie tous les "compteurs" a chaque iteration au lieu de le faire un par un, ce qui a pour consequence que quand je commande deux (ou 3,ou 5,ou 10) batiment je n'en construit qu'un seul. c'est d'autant plus incomprehensible que j'ai verifier la methode employer dans un programe test qui me donne des resultats satifaisant:
 
l=[[1,"a"],[1,"a"]]
a=0
while a < len(l):
                print "tour :" ,a,"  ",l
                l[a][0]=l[a][0]-1
                print "tour :" ,a,"  ",l
                if l[a][0]==0:
                     
                    print l[a][1]
                a=a+1

 
qui me donnent le resultat suivant:
 
tour : 0    [[1, 'a'], [1, 'a']]
tour : 0    [[0, 'a'], [1, 'a']]
a
tour : 1    [[0, 'a'], [1, 'a']]
tour : 1    [[0, 'a'], [0, 'a']]
a
 
je doit avouer que je ne vois pas de differences entre les deux programes et je ne comprend pas pourquoi la ligne self.construcList[a][0] = self.construcList[a][0]-1 ne me donne pas le memme resultat que l[a][0]=l[a][0]-1...
 
merci d'avance.

Reply

Marsh Posté le 26-08-2007 à 23:45:44   

Reply

Marsh Posté le 27-08-2007 à 10:39:45    

1. Je conseillerais de créer de vrais objets, ça serait une bonne idée. Par exemple un objet ConstructionTask prenant en paramètre une classe d'objet à construire e.g.

Code :
  1. class Building(object):
  2.    """ Classe de base pour tout les batiments,
  3.    y mettre les choses communes a tout ce qu'on peut construire
  4.    """
  5.    def build(self):
  6.        raise NotImplementedError()
  7.  
  8. class Farm(Building):
  9.    def build(self):
  10.        # gerer la construction d'une ferme ici
  11.        pass
  12.  
  13. class BuildTask(object):
  14.    def __init__(self, building, count):
  15.        self.building = building
  16.        self.count = count
  17.    def build(self):
  18.        # construire le batiment
  19.        b = self.building()
  20.        self.count -= 1
  21.        # faire un truc avec le batiment qu'on vient de construire
  22.        doSomethingWith(b)
  23.    def alive(self):
  24.        """ Verifie si la tache a encore des batiments a construire """
  25.        return self.count > 0
  26.    def __str__(self):
  27.        return "Building %d %s"%(self.count, str(self.building))
  28.  
  29. # creation d'une tache de construction
  30. task = BuildTask(Farm, 5)


Ce code est naturellement très rudimentaire, il ne gère pas le temps de construction et plein d'autres trucs, mais c'est un exemple

 

2. Si tu veux un équivalent des strucs C, utiliser des tuples, pas des lists: (5, "tour" ) plutôt que [5, "tour"], le rôle sous-tendant est plus clair: un tuple a une structure, une liste a un ordre (voir nombre de commentaires sur http://jtauber.com/blog/2006/04/15 [...] ant_lists/ sur le sujet)

 

3. Prière d'utiliser le Tuple Unpacking

 

4. Prière d'utiliser for et la fonction range() combinés au tuple unpacking, et potentiellement les List Comprehensions. Voir aussi enumerate

 

5. Favoriser l'immutabilité si tu utilises des tuples: régénérer une liste de constructions en intégralité à chaque tour par exemple (à ne pas faire si tu utilises le point 1 par contre)

 

Rien qu'avec les points 2 à 5, ton code prend une allure du type:

Code :
  1. def buildTower(self):
  2.    ## note: cette methode est horrible, avoir une methode
  3.    ## permettant de construire n'importe quoi à la place
  4.    ## et le nom ne correspond meme pas a ce que fait la
  5.    ## methode
  6.    newList = []
  7.    for (c, building) in self.constructList:
  8.        count = c - 1
  9.        if not count:
  10.            self.build(building)
  11.        else:
  12.            newList.append((count, building))
  13.    self.constructList = newList


shad233 a écrit :

ce qui me donnent les lignes suivante:

 

[[1, 'farm'], [1, 'farm']]
[[0, 'farm'], [0, 'farm']]
[[0, 'farm'], [0, 'farm']]
[[-1, 'farm'], [-1, 'farm']]


Chez moi ça marche:

Code :
  1. constructList = [[1, 'farm'], [1, 'farm']]
  2. a = 0
  3. while a < len(constructList):
  4.    print constructList
  5.    constructList[a][0] = constructList[a][0]-1
  6.    print constructList
  7.    if constructList[a][0]==0:
  8.        print "building", constructList[a][1]
  9.    a=a+1


renvoie

[[1, 'farm'], [1, 'farm']]
[[0, 'farm'], [1, 'farm']]
building farm
[[0, 'farm'], [1, 'farm']]
[[0, 'farm'], [0, 'farm']]
building farm


donc le bug est ailleurs dans ton code, généré par je ne sais quel effet de bord à la con

 

edit: je viens de voir un truc, le numéro que tu as associé à un bâtiment c'est quoi, le temps que ça prend à construire ou le nombre de bâtiments à construire?
Non parce que je remarque que je l'ai utilisé comme nombre de bâtiments à construire donc mes exemples de code alternatifs sont faux (par contre mes conseils restent totalement valables).

 

Si tu utilises ce chiffre comme le temps de construction du bâtiment, tu devrais utiliser une vraie queue ou au moins manipuler ta liste de construction (qui est en fait une FILE de constructions) en utilisant list.pop(0) et list.append()


Message édité par masklinn le 27-08-2007 à 23:41:18

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 27-08-2007 à 20:37:11    

merci pour ta reponse et les nombreuses pistes que tu ma donné. pour commencer, j'ai suivi ton conseil et je l'ai redefini en objet mais ca marchait toujour pas, finalment j'ai changer ma liste de construction pour recevoir non pas une liste mais une chaine avec le compteur integré et ca marche!
 
comme ca peut peut etre un jour interresser quelqu'un je met ma methode:
 
a=0
        if len(self.construcList) !=0:
            while a < len(self.construcList):
                b = self.construcList[a]# j'extraie la chaine de la liste
                c=list (b) # je la coupe en liste
                c[0]=int(c[0])# je transforme le compteur en nombre pour le modifier
                c[0]=c[0]-1 #je modifie le compteur
                c[0]=str(c[0])#je le retransforme en chaine
                e=""
                h=e.join(c)# je retrensforme le tout en chaine
                self.construcList[a]=h # je remplace l'anciene chaine par la nouvelle            
                if self.construcList[a][0]=="0":
                    print "plop"
                    nat.consSelecteur(self.construcList[a])        
                a=a+1  

 
au lieu d'une liste de la forme [1,"farm"] je traite une chaine de la forme "1farm" et c'est bien plus simple a gerer pour un debutant comme moi :p  
 
en tout cas merci, et puis grace a toi je vais m'interesser au tuples de plus prés^^

Reply

Marsh Posté le 27-08-2007 à 21:33:31    

shad233 a écrit :

merci pour ta reponse et les nombreuses pistes que tu ma donné. pour commencer, j'ai suivi ton conseil et je l'ai redefini en objet mais ca marchait toujour pas, finalment j'ai changer ma liste de construction pour recevoir non pas une liste mais une chaine avec le compteur integré et ca marche!
 
comme ca peut peut etre un jour interresser quelqu'un je met ma methode:
 
a=0
        if len(self.construcList) !=0:
            while a < len(self.construcList):
                b = self.construcList[a]# j'extraie la chaine de la liste
                c=list (b) # je la coupe en liste
                c[0]=int(c[0])# je transforme le compteur en nombre pour le modifier
                c[0]=c[0]-1 #je modifie le compteur
                c[0]=str(c[0])#je le retransforme en chaine
                e=""
                h=e.join(c)# je retrensforme le tout en chaine
                self.construcList[a]=h # je remplace l'anciene chaine par la nouvelle            
                if self.construcList[a][0]=="0":
                    print "plop"
                    nat.consSelecteur(self.construcList[a])        
                a=a+1  


C'est immonde [:pingouino]


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 27-08-2007 à 23:17:41    

Si tu débute en python il y a ce tuto: ftp://ftp-developpez.com/python/c [...] winnen.zip
 
Qui est vrement sympa ( au cas ou tu ne l'ai pas trouver ) perso j'ai commencer avec ça et je le trouve bien assez complet !

Reply

Marsh Posté le 27-08-2007 à 23:24:29    

Hmm, ta liste était une variable de classe et non d'instance, ce qui fait qu'elle avait la même valeur pour toutes les instances. C'est ça ?

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed