IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Voir le flux RSS

User

[Actualité] Python : simuler une planche de Galton sur un formulaire Tkinter

Note : 3 votes pour une moyenne de 3,67.
par , 26/06/2023 à 10h31 (5501 Affichages)
I. Introduction

Une planche de Galton est un dispositif qui illustre la convergence d'une loi binomiale vers une loi normale.

Des clous sont plantés sur la partie supérieure de la planche, de telle sorte qu'une bille lâchée sur la planche passe soit à droite soit à gauche pour chaque rangée de clous. Dans la partie inférieure les billes sont rassemblées en fonction du nombre de passages à gauche et de passages à droite qu'elles ont fait.

Ainsi chaque colonne correspond à un résultat possible d'une expérience binomiale (en tant qu'une expérience de Bernoulli répétée) et on peut remarquer que la répartition des billes dans les cases approche la forme d'une courbe de Gauss :

Nom : planche_galton.png
Affichages : 4759
Taille : 66,9 Ko

L'objectif de ce billet est de montrer comment simuler dans un formulaire Tkinter le déplacement aléatoire des billes sur une planche de Galton, pour obtenir à la fin, en bas de la planche, une répartition des billes suivant approximativement une loi normale.


Note : si vous souhaitez avoir plus d'information sur le sujet je vous invite à consulter la page Wikipedia Planche de Galton.



II. Classe PlancheGalton

Un widget canevas est un objet du module Tkinter permettant de dessiner des formes géométriques (rectangles, lignes, disques, etc.) et de les manipuler (personnalisation, déplacement, suppression, etc.) sur une surface.

On souhaite dans notre cas dessiner une planche de Galton sur une zone d'affichage d'un formulaire en utilisant un objet Canvas. Pour cela, on va créer une classe fille PlancheGalton qui va hériter de l'ensemble des attributs et des méthodes de la classe mère Canvas :

Nom : classe_PlancheGalton.png
Affichages : 3839
Taille : 16,3 Ko

On va donc commencer par ajouter en haut de notre module l'instruction :

Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
from tkinter import Canvas

Notre classe comportera donc un constructeur, c'est à dire une méthode particulière __init__() dont le code est exécuté quand la classe est instanciée.

Elle va nous permettre de définir en particulier le nombre de niveaux ou de rangées de clous sur la planche de Galton au moment de la création de l'objet :

Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class PlancheGalton(Canvas): # la classe hérite de tous les attributs et méthodes de Canvas
 
    def __init__(self, parent, width, height, background, nb_niveaux=24):
 
	# exécution de ma méthode __init__() de la classe Canvas
        Canvas.__init__(self, parent, width=width, height=height, background=background)
 
        # définit le nombre de rangées de clous ou de niveaux de la planche de Galton
        self.nb_niveaux = nb_niveaux
 
        # définit la hauteur des colonnes du bas
        self.hauteur_colonnes = nb_niveaux
 
        # dessine la planche de Galton avec nb_niveaux
        self.redessiner()

Elle contient également une méthode pour dessiner les rangées de clous sur la planche et une autre pour afficher une bille à une position précise :

Code Python : 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
class PlancheGalton(Canvas): # la classe hérite de tous les attributs et méthodes de Canvas
    ...
    def dessiner_bille(self, position_x, position_y, couleur):
        # largeur et hauteur du Canvas
        w = self.winfo_width() 
        h = self.winfo_height()
 
        # valeurs mini et maxi sur le Canvas suivant x et y
        min_x = -self.nb_niveaux-1; max_x = self.nb_niveaux + 1.05
        min_y = -0.05; max_y = self.nb_niveaux + self.hauteur_colonnes + 1
 
        # fonction de conversion des x et des y par rapport à la largeur w et la hauteur h du Canvas
        tx = lambda x: w * (x - min_x)/(-min_x + max_x)
        ty = lambda y: h * (y - min_y)/(-min_y + max_y)
 
        # l'écart entre 2 clous horizontaux sur la planche de Galton vaut 2
        # la hauteur entre 2 niveaux/rangée de clous vaut 1
 
        # valeurs des coordonnées x et y
        x = position_x
        y = min_y + position_y + 1.5
 
        # écart entre 2 rangée de clous
        ecart_y = 1
 
        # définition du rayon du cercle en fonction de l'espace entre les clous donc du nombre de niveaux
        r = int(0.85*(ty(ecart_y))/2) 
 
        # trace le cercle de rayon r et centré sur le point de coordonnées (tx(x), ty(y))        
        self.creer_cercle(tx(x), ty(y), r, fill=couleur, outline=couleur)
     ...

Le module contenant notre classe est enregistré sous le même nom PlancheGalton.py.



III. Formulaire Tkinter

On va présenter maintenant les différents composants du formulaire, puis on va décrire le code permettant de simuler le déplacement aléatoire des billes sur le planche de Galton.


III-A. Composants du formulaire

Il comporte sur sa partie supérieure des boutons de commandes pour lancer, arrêter ou initialiser la simulation.

Deux zones de texte permettent en plus de définir le nombre de rangées de clous horizontales sur la planche de Galton, et le nombre de billes pris en compte lors de la simulation.

Enfin, le reste du formulaire contient le widget canevas construit à partir de la classe PlancheGalton et sur lequel on va simuler le déplacement aléatoire des billes.

On a donc besoin d'ajouter en haut du module du formulaire des lignes de code permettant d'importer Tkinter et notre classe PlancheGalton contenue dans le fichier PlancheGalton.py :

Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
import tkinter
from PlancheGalton import PlancheGalton # on importe notre classe PlancheGalton à partir du fichier PlancheGalton.py

Ensuite, les différents objets sont ajoutés dans le formulaire Tkinter au moment de sa création, c'est à dire quand sa méthode __init__() est executée :

Code Python : 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
class SimulateurPlancheGalton(Tk):
 
    def __init__(self):
 
        # instantiation de la classe parente
        Tk.__init__(self)
 
        # conteneur vertical occupant tout le formulaire et destiné à contenir le widget à canvas  
        verticalPane = PanedWindow( self, orient=VERTICAL )
 
        # conteneur horizontal placé en haut du formulaire pour les différents contrôles du formulaire
        horizontalPane = PanedWindow( verticalPane, orient=HORIZONTAL )
 
        # création des boutons de commande
        btnLancer=Button( horizontalPane, text="Lancer", command=self.btnLancerClicked, width = 10)
        btnArreter=Button( horizontalPane, text="Arreter", command=self.btnArreterClicked, width = 10)
        btnInit=Button( horizontalPane, text="Initialiser", command=self.btnInitClicked, width = 10)
 
        # création des labels et des zones de texte
        lblNbNiveaux = Label( horizontalPane, text = "Nombre de niveaux")  
        self.txtNbNiveaux= Text(horizontalPane, height = 1, width = 11)
 
        lblNbBilles = Label( horizontalPane, text = "Nombre de billes") 
        self.txtNbBilles = Text(horizontalPane, height = 1, width = 11)
 
        # création d'un bouton supplémentaire permettant de finaliser la simulation
        btnFinaliser=Button( horizontalPane, text="Finaliser", command=self.btnFinaliserClicked, width = 11)
 
        # ajout des contrôles au conteneur horizontal
        horizontalPane.add( btnLancer )
        horizontalPane.add( btnArreter )
        horizontalPane.add( btnInit )
 
        horizontalPane.add( lblNbNiveaux )
        horizontalPane.add( self.txtNbNiveaux )
 
        horizontalPane.add( lblNbBilles )
        horizontalPane.add( self.txtNbBilles )
 
        horizontalPane.add( btnFinaliser )
 
        # ajout du conteneur horizontal
        verticalPane.add( horizontalPane )
        verticalPane.pack(expand=True, fill='both')
 
        # création de l'objet PlancheGalton
        self.planche_galton = PlancheGalton(verticalPane, 700, 700, "white", nb_niveaux=24)
 
        # ajout de l'objet au conteneur vertical
        verticalPane.add( self.planche_galton )
        verticalPane.pack(expand=True, fill='both')
 
        # met à jour l'objet Canvas pour récupérer les bonnes valeurs de winfo_width() et winfo_height() 
        self.planche_galton.update()
 
        self.planche_galton.redessiner()
 
        # définition du titre du formulaire
        self.title( "Planche de Galton V1.0" )
 
        # saisie des valeurs par défaut dans les zones de texte txtNbNiveaux et txtNbBilles
        self.txtNbNiveaux.insert(END,self.planche_galton.nb_niveaux)
        self.txtNbBilles.insert(END,100)
 
        # état du simulateur mis par défaut sur "Désactivé"
        self.etat_simulateur = "Désactivé"

Aperçu du formulaire :

Nom : formulaire.png
Affichages : 3863
Taille : 10,9 Ko


III-B. Contrôle du simulateur

On associe ensuite du code Python aux boutons de commande permettant de lancer, d'arrêter ou d'initialiser le simulateur :

Code Python : 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
    def btnLancerClicked(self):
 
        if self.etat_simulateur == "Désactivé":
            # initialisation de la simulation
            self.init_simulation()
 
        # lancement de la simulation : état "Activé"
        self.etat_simulateur = "Activé"
        # exécute la méthode simuler() de l'objet
        self.simuler()
 
    def btnArreterClicked(self):
 
        # arrêt de la simulation : état "Interrompu"
        self.etat_simulateur = "Interrompu"
 
    def btnInitClicked(self):
 
        # initialisation de la simulation : état "Désactivé"
        self.etat_simulateur = "Désactivé"
 
        # initialise les paramètres de la simulation et redessine la planche de Galton
        self.init_simulation()


III-C. Simulation du déplacement aléatoire des billes sur la planche

Dans cette partie, on va d'abord tirer au hasard les trajets des billes sur la planche, pour ensuite simuler la descente des billes à partir du tirage obtenu.


III-C-1. Tirage aléatoire des trajets des billes

Pour chaque bille, on parcourt les niveaux ou rangées de la planche de Galton, et pour chaque niveau on tire au hasard une valeur entre 0 et 1 :

  • 0 : descente à gauche du clou ;
  • 1 : descente à droite du clou.


On utilise pour cela la fonction choice du module random :

Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
dep_x = random.choice([0,1])

On ajoute ensuite la valeur obtenue à une liste représentant le trajet de la bille :

Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
trajet.append(dep_x)

Une fois la bille arrivée en bas de la planche, on obtient une liste de 0 et de 1 correspondant au parcours complet de la bille sur la planche :

[0, 0, 0, 0] : représente 4 descentes à gauche ;
[0, 0, 0, 1] : représente 3 descente à gauche et 1 à droite ;
[0, 0, 1, 1] : représente 2 descente à gauche et 2 à droite ;

etc..

Pour connaitre l'indice de la colonne finale dans laquelle tombe la bille, il suffit de faire la somme des 1 de la liste obtenue :

Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
indice_colonne = sum(trajet)

[0, 0, 0, 0] -> 0
[0, 0, 0, 1] -> 1
[0, 0, 1, 1] -> 2


etc..

Note : cet indice de colonne représente également le nombre de cas favorables ou de succès dans un schéma de bernoulli pour lequel le nombre d'épreuves correspond au nombre de rangées de clous.

On donne maintenant la fonction complète qui effectue le tirage aléatoire des trajets des billes :

Code Python : 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
def tirer_trajets(nb_niveaux, nb_billes):
 
    # initialise la liste des résultats avec des colonnes à 0
    liste_resultats = [0]*(nb_niveaux+1)
 
    # initialise la liste des trajets des billes
    tirage_trajets=[]
 
    # initialise le générateur aléatoire
    random.seed()
 
    # parcours des indices des billes : 0, 1, 2, .., nb_billes-1
    for indice_bille in range(nb_billes):
 
        # initialisation de la liste représentant le trajet aléatoire de la bille
        trajet = []
 
        # parcours des indices des niveaux : 0, 1, 2, .., nb_niveaux-1
        for indice_niveau in range(nb_niveaux):
 
            # on tire au hasard une valeur entre 0 et 1 (0 : descente vers la gauche du clou, 1 : descendre vers la droite)
            dep_x = random.choice([0,1])
 
            # ajout du choix au trajet
            trajet.append(dep_x)
 
        # ajout du trajet à la liste
        tirage_trajets.append(trajet)
 
        # indice de la colonne finale égal à la somme des 0 et des 1 de la liste obtenue
        indice_colonne = sum(trajet)
 
        # incrémentation du nombre de billes dans la colonne
        liste_resultats[indice_colonne] += 1
 
    # renvoi des listes obtenues
    return (tirage_trajets, liste_resultats)


III-C-2. Simulation des trajets des billes à partir du tirage précédent

On dispose à ce stade de la liste des trajets des billes qui sont représentés par des séquences de 0 et de 1. Par exemple pour une planche à 4 niveaux on peut avoir [0, 1, 0, 1], [0, 1, 1, 1], etc.

Il ne reste donc plus qu'à dessiner les billes à leurs positions successives sur le canvas en parcourant les séquences de 0 et de 1.

On ajoute pour cela une méthode simuler() à la classe SimulateurPlancheGalton permettant de simuler le déplacement aléatoire des billes sur la planche de Galton :

Code Python : 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
    def simuler(self):
 
        # si une simulation est en cours
        if self.etat_simulateur == "Activé":
 
            en_cours = False
 
            # parcours des indices des billes
            for indice_bille in range(self.nb_billes):
 
                # position actuelle ou prochaine position de la bille : (position_x, position_y)
                position_x, position_y = self.positions_billes[indice_bille][0], self.positions_billes[indice_bille][1]
 
                # si la bille est à cette position
                if self.tableau_etats[position_y][position_x] == indice_bille:
 
                    position_suiv_x = position_x
 
                    if position_y < self.planche_galton.nb_niveaux:
 
                        dep_x = self.tirage_trajets[indice_bille][position_y] # dep_x = random.choice([0,1]) pour une simulation en temps réel
 
                        if dep_x==0: # si le caractère de descente vers la gauche est choisi
                            position_suiv_x = position_x - 1 # déplacement vers la gauche
                        else: # sinon
                            position_suiv_x = position_x + 1 # déplacement vers la droite
 
                    position_suiv_y = position_y + 1 # déplacement vers le bas
 
                    # si pas de bille à la position (position_suiv_x, position_suiv_y)
                    if self.tableau_etats[position_suiv_y][position_suiv_x] is None:
 
                        en_cours = True
 
                        # efface la bille à la position de coordonnées (position_x, position_y)
                        self.planche_galton.dessiner_bille(position_x, position_y, "white")
 
                        # met l'état de la position dans le tableau à None
                        self.tableau_etats[position_y][position_x] = None
 
                        # affiche une bille bleu à la position de coordonnées (position_suiv_x, position_suiv_y)
                        self.planche_galton.dessiner_bille(position_suiv_x, position_suiv_y, "blue")
 
                        self.positions_billes[indice_bille] = (position_suiv_x, position_suiv_y)
 
                        if position_suiv_y<(self.planche_galton.nb_niveaux + self.planche_galton.hauteur_colonnes - 1):
                            self.tableau_etats[position_suiv_y][position_suiv_x] = indice_bille
                        else:
                            self.tableau_etats[position_suiv_y][position_suiv_x] = -1
 
                # sinon, si pas de bille à la position de coordonnées (position_x, position_y)
                elif self.tableau_etats[position_y][position_x] is None and (position_y==0):
 
                    en_cours = True
                    # on positionne la bille à cet emplacement
                    self.tableau_etats[position_y][position_x] = indice_bille
                    self.positions_billes[indice_bille] = (position_x, position_y)
 
                    self.planche_galton.dessiner_bille(position_x, position_y, "blue")
 
            # si au moins une bille est toujours en progression sur la planche de Galton
            if en_cours:
                self.after(250, self.simuler) #
            else:
                self.etat_simulateur = "Désactivé"
                self.finaliser_simulation() # finalise la simulation

Cette méthode est exécutée toutes les 250 millisecondes grâce à la commande :

Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
self.after(250, self.simuler)

Note : quand le nombre de billes sur la planche devient important, il se produit un ralentissement de la procédure, c'est pourquoi on a prévu une fonction permettant de finaliser la simulation et ainsi d'obtenir directement le résultat dans les colonnes du bas :

Code Python : 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
    def finaliser_simulation(self):
        # finalisation de la descente des billes sur la planche de Galton
        # comparaison entre la répartition des billes obtenue dans les colonnes du bas de la plannche et une répartition suivant une loi normale
 
        # nombre de colonnes du bas et dernière ligne de la planche de Galton  
        nb_colonnes = self.planche_galton.nb_niveaux + 1        
        position_max_y = self.planche_galton.nb_niveaux + self.planche_galton.hauteur_colonnes
 
        # moyenne et écart-type de la loi normale
        m = self.planche_galton.nb_niveaux/2.0; s = pow(self.planche_galton.nb_niveaux,0.5)/2.0
 
        # parcours des indices de colonne : 0, 1, 2, .., nb_colonnes-1 
        for indice_colonne in range(nb_colonnes):
 
            # position par rapport à l'axe x
            position_x = 2*indice_colonne - self.planche_galton.nb_niveaux
 
            # évaluation du nombre de billes attendu dans la colonne repérée par indice_colonne :
            # nombre approximatif de billes évalué à l'aide de la fonction de répartition de la loi normale
            nb_billes_col = (stats.norm.cdf(indice_colonne+1-0.5, loc=m, scale=s) - stats.norm.cdf(indice_colonne-0.5, loc=m, scale=s))*self.nb_billes
 
            # position supérieure et inférieure du rectangle représentant le nombre de billes donné par la fonction de répartition de la loi normale
            position_y1 = position_max_y - nb_billes_col
            position_y2 = position_max_y 
 
            # dessine un rectangle de coordonnées (position_x-0.8, position_y1, position_x+0.8, position_y2) : hauteur donnée par la fonction de répartition de la loi normale
            self.planche_galton.dessiner_rectangle(position_x-0.8, position_y1, position_x+0.8, position_y2, "orange")
 
            position_min_y = position_max_y - self.resultats[indice_colonne]
 
            # parcours des positions suivant l'axe y
            for position_y in range(position_min_y, position_max_y):                
                # dessine la bille à la position de coordonnées (position_x, position_y)
                self.planche_galton.dessiner_bille(position_x, position_y, "blue")
 
        # traçage de la courbe de Gauss
        # parcours des indices de colonne : 0, 1, 2, .., nb_colonnes-1 
        for indice_colonne in range(nb_colonnes):
 
            # traçage de la courbe sur l'intervalle [a, b]
            a = indice_colonne-0.5 ; b=indice_colonne+1-0.5
 
            # pas de subdivision
            pas = (b-a)/40
 
            # parcours des subdivisions de l'intervalle [a,b]
            for i in range(40):
 
                # calcul des coordonnées de x et y
                x = a + i*pas
                # valeur de y obtenue à l'aide de la fonction de densité de la loi normale
                y = stats.norm.pdf(x, loc=m, scale=s)*self.nb_billes 
 
                # positions correspondantes sur le Canvas
                position_x = 2*x - self.planche_galton.nb_niveaux
                position_y = position_max_y - y
 
                # dessine un point rouge de coordonnées (position_x, position_y)
                self.planche_galton.dessiner_point(position_x, position_y, "red")

Il s'agit donc d'une simulation pré-enregistrée, mais vous pouvez également changer dans la fonction simuler() la commande :

Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
dep_x = self.tirage_trajets[indice_bille][position_y]
En :

Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
dep_x = random.choice([0,1])

Pour obtenir ainsi une simulation en temps-réel.


IV. Modules de test

On a donc besoin de 2 modules pour réaliser cette simulation :

  • PlancheGalton.py est utilisé pour dessiner la planche de Galton sur une zone d'affichage ;
  • SimulateurPlancheGalton.py permet de simuler dans un formulaire Tkinter la descente aléatoire des billes sur une planche de Galton.

Si vous le souhaitez, vous pouvez télécharger le dossier complet pour effectuer les tests :

simulateur_planche_galton.zip

On teste maintenant le simulateur en choisissant par exemple 24 rangées de clous pour la planche de Galton, et 100 billes en entrée.

Après avoir lancé la simulation, on peut visualiser la descente aléatoire des billes sur la planche de Galton :

Nom : simulation_planche_galton.png
Affichages : 3848
Taille : 14,4 Ko

A la fin, on obtient une répartition des billes suivant approximativement une loi normale :

Nom : resultats_simulation.png
Affichages : 3859
Taille : 16,4 Ko


V. Conclusion

Après avoir créé la classe PlancheGalton, nous avons pu l'utiliser pour simuler sur un formulaire Tkinter une planche de Galton.

Chacun pourra ensuite librement personnaliser ou améliorer la simulation en ajoutant par exemple un léger effet de rebond des billes sur les clous.

Sources :

https://fr.wikipedia.org/wiki/Planche_de_Galton
https://fr.wikipedia.org/wiki/%C3%89...a_de_Bernoulli
https://docs.python.org/fr/3.11/library/tkinter.html
https://www.tutorialspoint.com/python/tk_canvas.htm
https://www.mathweb.fr/euclide/simul...ton-en-python/

Téléchargement :
simulateur_planche_galton.zip

Envoyer le billet « Python : simuler une planche de Galton sur un formulaire Tkinter » dans le blog Viadeo Envoyer le billet « Python : simuler une planche de Galton sur un formulaire Tkinter » dans le blog Twitter Envoyer le billet « Python : simuler une planche de Galton sur un formulaire Tkinter » dans le blog Google Envoyer le billet « Python : simuler une planche de Galton sur un formulaire Tkinter » dans le blog Facebook Envoyer le billet « Python : simuler une planche de Galton sur un formulaire Tkinter » dans le blog Digg Envoyer le billet « Python : simuler une planche de Galton sur un formulaire Tkinter » dans le blog Delicious Envoyer le billet « Python : simuler une planche de Galton sur un formulaire Tkinter » dans le blog MySpace Envoyer le billet « Python : simuler une planche de Galton sur un formulaire Tkinter » dans le blog Yahoo

Mis à jour 28/08/2023 à 07h37 par User

Catégories
Programmation , Python , Algorithmique

Commentaires

  1. Avatar de f-leb
    • |
    • permalink
    Marrant Par contre, l'animation ralentit sérieusement chez moi au fur et à mesure de l'apparition des billes. Bizarre...


    Edit : Programme qui fonctionne très bien dans une VM sous Linux, j'ai donc une m#@! à résoudre sous Windows
    Mis à jour 05/07/2023 à 16h51 par f-leb
  2. Avatar de User
    • |
    • permalink
    Merci Fabien

    Mais tu as en partie raison, comme je l'indique plus il y a de billes sur la planche et plus ça ralenti, d'où l'utilité du bouton finaliser qui donne le résultat de la simulation
  3. Avatar de f-leb
    • |
    • permalink
    Citation Envoyé par User
    Merci Fabien

    Mais tu as en partie raison, comme je l'indique plus il y a de billes sur la planche et plus ça ralenti, d'où l'utilité du bouton finaliser qui donne le résultat de la simulation

    Oui oui, mais vu la lenteur avec peu de billes alors que ça fonctionne très bien dans une VM Linux sur la même machine, j'ai vraiment un problème pas normal sous Windows