IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Jeu de la vie


Sujet :

Python

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4
    Par défaut Jeu de la vie
    Hey!

    Je dois faire un jeu de la vie(http://fr.wikipedia.org/wiki/Jeu_de_la_vie) pour la fac et j'ai un souci que je n'arrive pas à expliquer.

    En effet, sachant que mon premier tableau de booléens représentant les cellules (tableau d'int 0 et 1 en fait, mais je chipote pas)donne "naissance" correctement à un second tableau, logiquement issu du premier en suivant les règles du jeu de la vie, je ne comprends pas pourquoi il n'en est pas de même quand je passe du tableau 2 au tableau 3.
    En gros :
    tableau 1-->tableau 2 : correct et logique
    tableau 2-->tableau 3 : Echec

    L'erreur ne se situe donc à priori ni dans la fonction qui permet de passer d'un tableau à un autre, sans quoi je n'aurais pas un bon tableau 2; ni dans le tableau 2, source du tableau 3.

    Voici le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    # -*- coding: cp1252 -*-
    import numpy as N
    import math as M
    from pylab import *
    from random import randrange
     
    #fonction qui permet de savoir si un indice est dans le tableau
    def Inb(IND, dim):
            return ((IND>=0)and(IND<dim))
    #Fonction qui 'convertit' une valeur du tableau en booleen
    def BOL(tab, i, j):
            if (tab[i, j]==1):
                    return True
            else:
                    return False
     
    #fonction qui calcule le nombre de cellules autour d'une cellule donnee.
    def Somme(tab, i, j):
            Som=0
            dim=4
            ##On verifie tout au long de la fonction qu'on "regarde" bien dans le tableau
            ##et pas en dehors. La fonction agit comme si l'exterieur du tableau ne 
            ##contenait que des zeros.
            Bi=N.arange(i-1, i+2, 1)
            Bj=N.arange(j-1, j+2, 1)
     
            for I in Bi:
                    for J in Bj:
                            if((Inb(I, dim))and(Inb(J, dim))and(BOL(tab, I, J))):
                                Som+=1
     
            if(BOL(tab, i, j)) :
                    Som-=1
            return Som
     
    ##On cree un tableau de booleens 4x4
    dim=4
    a=N.zeros((dim,dim), dtype=int)
     
    b=N.arange(0, dim, 1)
     
    ##Je me sers des trois methodes suivantes pour creer le tableau initial
    ##et le tester.
     
    ##Creation aleatoire du tableau carre de booleens
     
    ##for i in b:
    ##	for j in b:
    ##		if (round(N.random.random(1)*100))>100:
    ##			a[i][j]=0
    ##		else:
    ##			a[i][j]=1
     
    ## Creation aleatoire avec choix du nombre de cellules initial.
    ##Nbcel=input('Nbcel?\n')
    ##IND=0
    ##while IND<Nbcel:
    ##
    ##        i=randrange(0, dim)
    ##        j=randrange(0, dim)
    ##        a[i][j]=1
    ##        IND+=1
     
    ##Creation specifique de cellules dans le tableau initial.
     
    a[0][0]=1        
    a[0][1]=1
    a[0][2]=1
    a[2][1]=1
    a[3][1]=1
    a[2][2]=1
    a[1][3]=1
     
     
    print ("Tableau de cellules initial:\n")
    print a
    print
     
     
     
    c=N.zeros((dim, dim), dtype=int)
    SOMME=N.zeros((dim, dim), dtype=int)
     
    #Fonction qui effectue un tour, ou cycle de vie
     
    def tour(A):
     
            for i in b:
                    for j in b:
     
                            ##La ligne suivante ne sers qu'a pouvoir afficher
                            ##si besoin est un tableau representant pour chaque
                            ##case la somme du nombre de cellules avoisinantes.
     
                            SOMME[i][j]=Somme(A, i, j)
     
                            ##Si la case ne contient pas de cellule...
                            if (A[i][j]==0):
                                    ##Et qu'il y a exactement 3 cellules autour
                                    if(Somme(A, i, j)==3):
                                            ##Alors une cellule sera cree a cet
                                            ##endroit dans le tableau representant
                                            ##le cycle suivant
                                            c[i][j]=1
                                    ##Sinon, si il n'y a pas 3 cellules autour:
                                    else:
                                            c[i][j]=0
     
                            ##Sinon, si la case contient une cellule...                
                            else:
                                    ##et qu'il n'y a ni 2 ni 3 cellules autour...
                                    if ((Somme(A, i, j)!=2)and(Somme(A, i, j)!=3)):
                                            ##Alors la cellule mourra.
                                            c[i][j]=0
                                    ##Sinon, elle reste en vie.
                                    else:
                                            c[i][j]=1
     
            return c                                
     
    #debut du premier tour
    Nbiter=input("Nombre d'iterations?\n")
    iter=0
    c=tour(a)
    ##La boucle tournera autant de fois qu'il y a d'iterations
    while iter<Nbiter:
            ##On affiche d'abord c, donc tour(a)
            print c
            print
            print ("SOMME:")
            print SOMME
            print
            ##Puis on stocke tour(c), soit tour(tour(a)) dans c pour le prochain cycle.
            c=tour(c)
     
            iter+=1
     
    ##DEBUG : Tour 1 parfait, tour 2 mauvais. Boucle correcte normalement.

  2. #2
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    Bonjour,

    Un petite remarque d'abord: évite d'importer des modules que tu n'utilises pas (pylab), surtout quand ce n'est pas un module de la librairie standard et que tu postes le code sur un forum; cela réduit le nombre de personnes susceptibles de te répondre. De même, le module numpy est certes utilisé, mais il n'apporte pas grand chose ici; tu aurais pu t'en passer facilement.

    Maintenant pour répondre à ta question: ton problème vient du fait que dans la fonction tour, tu modifies le contenu de la variable globale c alors que celle-ci contient également ton tableau de départ. Déplace l'initialisation de c dans la fonction tour pour en faire une variable locale et ton problème est résolu:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    def tour(A):
        c=N.zeros((dim, dim), dtype=int)
        ...
    Le problème n'apparaissait pas à la première génération car le tableau initial est dans la variable a et non c.

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4
    Par défaut
    Pour les modules : on nous oblige à les importer d'office en cours, je suis bien d'accord pour dire que c'est d'une inutilité flagrante mais bon.
    Sinon je ne savais pas qu'en Python les variables d'une fonction étaient globales d'office (je suis plus C++/Java), mais ça restait une erreur de ma part, donc merci bien de ta réponse, problème reglé

  4. #4
    Membre émérite
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Par défaut
    Citation Envoyé par Solokian Voir le message
    Sinon je ne savais pas qu'en Python les variables d'une fonction étaient globales d'office
    bonjour,

    en python les variables ne sont pas d'office "globales", elles sont liées à la portée qui les lie:

    - si tu définis une variable dans une fonction, elle est détruite à la fin de la fonction

    - si tu définis une variable dans une boucle, elle est détruite à la fin de la boucle

    - etc...

    dans ton cas la variable c est liée à ton script puisqu'elle n'est pas définie dans une fonction particulière et donc accessible dans l'ensemble des fonctions définies dans ton script.

    pour éviter ce "comportement", tu peux structurer ton code comme ceci:

    - tu déclares tes fonctions comme tu l'as fait
    - tu crées une fonction main qui contient tout le corps de ton programme (qui n'est pas déjà dans une fonction)
    - à la fin de ton script tu fais:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if __name__ == "__main__":
        main()
    dans ce cas, c ne sera plus globale puisque liée à la portée de la fonction main.

  5. #5
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    Citation Envoyé par kango Voir le message
    - si tu définis une variable dans une fonction, elle est détruite à la fin de la fonction

    - si tu définis une variable dans une boucle, elle est détruite à la fin de la boucle

    - etc...
    D'accord pour la fonction, mais il n'y a pas de portée limitée à une boucle ni autre chose.
    Il n'y a que deux types de portées:
    1) la portée globale: la durée de vie est celle de l'interpéteur (à moins d'être explicitement détruite par un 'del')
    2) la portée locale (à une fonction). Comme les fonctions peuvent être imbriquées, les portées locales aussi. La variable est "détruite" en fin de fonction, mais attention cela ne signifie pas forcément que son contenu sera détruit (ce ne sera le cas que si celui-ci n'est plus référencé ailleurs,cf. comptage de références).

    Lors de l'accès à la valeur d'une variable dans une fonction, si celle-ci n'est pas trouvée dans la portée locale, on remonte dans la portée locale de la fonction englobante s'il y en a, et ainsi de suite tant que la variable n'est pas trouvée, et en final à la portée globale.

    La modification de la valeur d'une variable (affectation) se fait toujours dans la portée locale, en créant la variable s'il le faut, sans remonter les portées englobantes (c'est lié au fait que les variables ne sont pas déclarées). Seule exception: si on déclare explicitement une variable avec le mot-clé 'global' dans une fonction; l'accès et l'affectation se feront à une variable globale.

  6. #6
    Membre émérite
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Par défaut
    oui j'ai dit une bêtise sur la portée dans une boucle, désolé si j'ai induit des gens en erreur et merci de m'avoir corrigé.

    Lors de l'accès à la valeur d'une variable dans une fonction, si celle-ci n'est pas trouvée dans la portée locale, on remonte dans la portée locale de la fonction englobante s'il y en a, et ainsi de suite tant que la variable n'est pas trouvée, et en final à la portée globale.
    exact, je n'avais jamais remarqué.

  7. #7
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4
    Par défaut
    Vu que là ma variable SOMME est modifiée dans une fonction, et affichée à l'extérieur. Et ça n'affiche pas du tout la valeur initiale, évidemment

Discussions similaires

  1. Problème jeu de la vie de Wolfram
    Par romromp dans le forum Pascal
    Réponses: 14
    Dernier message: 11/03/2007, 19h58
  2. algorithme d'évolution du "jeu de la vie" en caml
    Par nono88 dans le forum Algorithmes et structures de données
    Réponses: 6
    Dernier message: 13/12/2006, 00h56
  3. Conway's life (jeu de la vie) pour images
    Par O( N ) dans le forum C
    Réponses: 1
    Dernier message: 26/09/2006, 02h13
  4. [Conception] Jeu de la vie
    Par deuscapser dans le forum Général Java
    Réponses: 16
    Dernier message: 09/03/2006, 12h47
  5. [VB] projet à réaliser: Jeu de la vie
    Par mauriiice dans le forum VB 6 et antérieur
    Réponses: 5
    Dernier message: 02/12/2005, 20h06

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo