Bonjour à tous, je suis en train de créer une sorte d'algorithme neuronal pour gagner au morpion (je laisse le jeu de go aux amateurs... :-°)

Pour enregistrer un grand nombre de partie, j'ai opté pour une structure d'arbre où la profondeur p correspond à l'emplacement joué au tour p.

Je veux donc faire un tableau qui enregistre les parties gagnées, et un autre pour les parties perdues; mais le problème c'est que lorsque j'ajoute un élément à un arbre, cet élément est également ajouté au deuxième arbre (comme si les deux variables ont la même référence).

je vous montre le code de la classe Arbre (seule la fonction ajouter est utilisé pour l'instant) :
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
class Arbre():
    """
    Un abre contient des parties sous forme de liste : la liste [4,0,1,5,7] correspond à:
                                                            -J1 joue en 4
                                                            -J2 joue en 0
                                                            -J1 joue en 1
                                                            -J2 joue en 5, etc...
    on accède à toute les parties avec arbre.lister(); mais la recherche d'une partie est en O(ln(9)), donc très rapide
    """
 
    def __init__(self,value=None,fils=[]):
        self.fils = fils
        self.value = value
 
 
    def ajouter(self,liste):
        """
        ajoute une partie à l'arbre
        """
        if liste == []:   #On est arrivé à la fin de la partie
            return None
        v = liste[0]
        for k in self.fils:
            if k.value == v:     #Si une partie commencant de la même manière existe déja
                return k.ajouter(liste[1:])  #On ajoute la fin de cette partie au fils correspondant
        #Sinon
        a = Arbre(v,[])
        a.ajouter(liste[1:])
        self.fils.append(a)  #on créé une nouvelle branche contenant la partie
 
    def descendre(self, valeur):
        """
        accéder au sous-arbre (au fils) correspondant au parties commençant par 'valeur', utilisé pour la recherche de partie
        Si aucune partie ne correspond, on renvoie None
        """ 
        for k in self.fils:
            if k.value == value:
                return k
        return None
 
    def lister(self):
        """
        Renvoie un tableau avec toutes les parties enregistrées dans l'arbre
        """
        if self.fils == []:
            return [[self.value]]
        l=[]
        for k in self.fils:
            l+=[ [self.value]+v for v in k.lister() ]
        return l
 
    def fils_aleat(self):
        """
        Pour plus tard, lors d'une partie, on joue aléatoirment parmis les coup ayant déja été enregstré comme gagnant
        """
        return self.fils[randint(0,len(self.fils)-1)]
et le code pour remplir les arbres (comprendre le principe des fonctions n'est pas nécéssaire, elles sont fonctionnelles) :
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
from random import randint
 
def gagne(pions):
 
    lignes = [ [0,1,2],   # la grille est :       0 | 1 | 2
            [3,4,5],      #                       ---------              
            [6,7,8],      #                       3 | 4 | 5             
            [0,3,6],      #                       ----------                     
            [1,4,7],      #                       6 | 7 | 8                    
            [2,5,8],      #                                                      
            [0,4,8], 
            [2,4,6] ]     #j'ai noté les lignes gagnantes 
 
    for l in lignes:
        aux = True     #On regarde si la ligne l est rempie
        for k in l:
            if not(k in pions):
                aux = False
        if aux==True:
            return True
    return False
 
def simulationAleat(arbreGagne,arbrePerds):
    t=True
    pions_joueur = []
    pions_ordi = []
    cases_libres = [k for k in range(9)]
    historique = []  #le tableau correspondant à la partie en cours
    while True:
        if len(cases_libres)==0:
            return None
        if t:  #C'est à l'ordi de jouer
            k = cases_libres[randint(0,len(cases_libres)-1)] #Il joue aléatoirement parmis les cases disponibles
            pions_ordi.append(k)   #On place le pion
            cases_libres.remove(k)  #La case est plus dispo
            historique.append(k)   #on met à jour la parie
            if gagne(pions_ordi):      #si l'ordi gagne, la partie est enregistré
                arbreGagne.ajouter(historique)
                return None
        else: #C'est la même chose mais c'est au tour du joueur (qui joue aussi aléatoirement)
            k = cases_libres[randint(0,len(cases_libres)-1)]
            pions_joueur.append(k)
            cases_libres.remove(k)
            historique.append(k)
            if gagne(pions_joueur):  #Si le joueur gagne
                arbrePerds.ajouter(historique)
                return None
        t=not(t)
 
def remplirArbre(n):  #on simule n parties
    G=Arbre(value=None)
    P=Arbre(value=None)
    for k in range(n):
        simulationAleat(G,P)
    return G,P
Pour accéder à l'ensemble des parties, c'est la fonction Arbre.lister(),

Essayez de taper :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
G,P=remplirArbre(100)
print(G.lister())
print(P.lister())
les tableaux sont égaux !

Merci d'avance, je peux apporter plus d'info sur la structure du programme si nécessaire.