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 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
|
""" chargement des bibliothèques """
from math import *
from tkinter import *
import numpy as np
import random as random
""" Création de la fenêtre principale (main window) """
Mafenetre = Tk()
Mafenetre.title('Animation')
""" Initialisation des variables globales (éventuellement des fonctions)"""
#1 : la case est saine
#2 : la case a brulé
# Tableau des vecteurs de déplacements
Deplacements = []
for i in [-1,0,1]:
for j in [-1,0,1]:
if i != 0 or j != 0:
Deplacements.append(np.array([i,j]))
v=random.randint(-1,1)
w=random.randint(-1,1)
DepVent=np.array([v,w])
print (DepVent)
# Tableau de codage
def Tableau(nblig, nbcol):
Tab = np.zeros([nblig,nbcol])
for lig in range(nblig):
for col in range(nbcol):
code = random.randint(50,99)
Tab[lig,col] = ForêtNonBrulée
Canevas.create_rectangle(col*distance, lig*distance,col*distance+distance, lig*distance+distance, fill="#00"+str(code)+"00")
return Tab
# Autres variables globales
Hauteur, Largeur = 0, 0
distance = 20
File = []
A = 0
posx=0
posy=0
ForêtNonBrulée=1
ForêtBrulée=2
ForêtPompier=3
# Simulation du vent
def Vent(p,i,DepVent):
a=0
Dep=i
for z in [-1,1]:
if DepVent[0]== Dep[0] and DepVent[1]== Dep[1] :
a=p*1.7
return a
elif (DepVent[0]==Dep[0]+z and DepVent[1]==Dep[1]+0) or (DepVent[0]==Dep[0]+0 and DepVent[1]==Dep[1]+z) :
a=p*1.3
return a
elif DepVent[0]==-1*Dep[0] and DepVent[1]== -1*Dep[1]:
a=p*0.4
return a
elif (DepVent[0]== -1*Dep[0]+z and DepVent[1]== -1*Dep[1]+0) or (DepVent[0]== -1*Dep[0]+0 and DepVent[1]== -1*Dep[1]+z) :
a=p*0.7
return a
else :
return p
""" Fonctions déclenchées par l'activation des widgets """
# Lecture des widgets de saisies (widgets Entry)
def litC(event):
global Hauteur
Hauteur = distance*eval(LectureC.get())
LectureC.configure(bg="lightblue")
def litD(event):
global Largeur
Largeur = distance*eval(LectureD.get())
LectureD.configure(bg="lightblue")
# Fonction déclenchée par clic de souris gauche sur le graphique
def Clic(event):
global File, posx, posy, pompier
X = event.x
Y = event.y
X = int(X/distance)*distance
Y = int(Y/distance)*distance
# on dessine un carré orange
Canevas.create_rectangle(X, Y, X+distance, Y+distance, outline='black',fill='orange')
File.append((Y//distance,X//distance))
pompier = Canevas.create_oval(posx+distance*0.1,posy+distance*0.1,posx+distance*0.9,posy+distance*0.9,outline='black',fill='red') #apparition pompier avec le clic
# Fonction de configuration du Canevas (fenêtre graphique). Grille pour le canevas.
# Cette fonction est déclenchée en appuyant sur le bouton Grille.
def afficheGrille():
global A,B
Canevas.configure(width = Largeur, height =Hauteur, bg ='white')
Canevas.pack(side = LEFT, padx = 5, pady = 5)
for x in range(distance, Largeur, distance):
Canevas.create_line(x, 0, x, Hauteur, fill="#476042")
for y in range(distance, Hauteur, distance):
Canevas.create_line(0, y, Largeur, y, fill="#476042")
# Appel à la fonction Tableau
A = Tableau(Hauteur//distance, Largeur//distance)
# Fonction de départ du feu. Cette fonction est déclenchée par le bouton Départ.
def Incendie():
global A, File, v, DepVent, posx, posy
nblig = Hauteur//distance
nbcol = Largeur//distance
if (len(File) > 0):
lig, col = File[0]
A[lig,col] = 2
for dep in Deplacements:
newPos = np.array([lig,col]) + dep
if (0 <= newPos[0] < nblig) and (0 <= newPos[1] < nbcol) and A[newPos[0], newPos[1]] != ForêtBrulée : #Si dans le tableau et non brulée
p=0.5
proba=Vent(p,dep,DepVent) # probabilité en fonction du vent initialement defini
c=random.random()
if c < proba:
if A[newPos[0], newPos[1]] != ForêtPompier : #Si le pompier n'est pas présent
File.append((newPos[0], newPos[1]))
Canevas.create_rectangle(newPos[1]*distance, newPos[0]*distance, newPos[1]*distance+distance, newPos[0]*distance+distance, fill="#907500")
A[newPos[0], newPos[1]] = ForêtBrulée
Canevas.create_rectangle(col*distance, lig*distance, col*distance+distance, lig*distance+distance, fill="#999999")
File.remove((lig,col))
Mafenetre.after(1000,Incendie)
# fonction déclenchée par le bouton de sortie (croix en haut à droite)
def quitApp():
Mafenetre.quit()
Mafenetre.destroy()
# fonction déplacement pompier
def Deplace(dep):
global posx, posy, pompier, A
nblig = Hauteur//distance
nbcol = Largeur//distance
Deplacement = [np.array([0,-1]),np.array([-1,0]),np.array([0,1]),np.array([1,0])]
vectDep = Deplacement[dep]
newPos = np.array([posx,posy]) + vectDep
if (0 <= newPos[0] < nblig) and (0 <= newPos[1] < nbcol):
if (A[newPos[0],newPos[1]]==ForêtNonBrulée):
posx = newPos[0]
posy = newPos[1]
A[posx,posy]=ForêtPompier
Canevas.coords(pompier, distance*(posx + 0.1), distance*(posy + 0.1), distance*(posx + 0.9), distance*(posy + 0.9))
""" Initialisation des Widgets """
# Initialisation du canevas (fenêtre graphique)
Canevas = Canvas(Mafenetre, width = 1, height = 1, bg ='white')
Canevas.bind('<Button-1>', Clic)
# Création d'une sous-fenêtre à droite du graphique
fenetre = Frame(Mafenetre, borderwidth=2, relief=GROOVE)
fenetre.pack(side=RIGHT, padx=10, pady=10)
# Champs de saisies(dans la sous-fenêtre)
C = Label(fenetre, text = "Hauteur?(Appuyez sur Entrée)")
C.pack(side=TOP, padx=10, pady=10)
LectureC = Entry(fenetre)
LectureC.pack(side=TOP, padx = 10, pady = 10)
LectureC.bind("<Return>", litC) # L'appui sur la touche "return" appelle la fonction litC.
D = Label(fenetre, text = "Largeur? (Appuyez sur Entrée)")
D.pack(side=TOP, padx=10, pady=10)
LectureD = Entry(fenetre)
LectureD.pack(side=TOP, padx = 10, pady = 10)
LectureD.bind("<Return>", litD)
# Boutons (dans la sous-fenêtre)
BoutonGrille = Button(fenetre, text ='Grille', command = afficheGrille)
BoutonGrille.pack(side = TOP, padx = 10, pady = 10)
BoutonDepart = Button(fenetre, text ='Départ (Cliquez sur une case au préalable)', command = Incendie)
BoutonDepart.pack(side = TOP, padx = 10, pady = 10)
# Boutons pompier
BoutonHaut = Button(fenetre, text ='Haut', command = lambda: Deplace(0))
BoutonHaut.pack(side = TOP, padx = 10, pady = 10)
BoutonBas = Button(fenetre, text ='Bas', command = lambda: Deplace(2))
BoutonBas.pack(side = BOTTOM, padx = 10, pady = 10)
BoutonGauche = Button(fenetre, text ='Gauche', command = lambda: Deplace(1))
BoutonGauche.pack(side = LEFT, padx = 10, pady = 10)
BoutonDroite = Button(fenetre, text ='Droite', command = lambda: Deplace(3))
BoutonDroite.pack(side = RIGHT, padx = 10, pady = 10)
# définition du bouton de sortie
Mafenetre.protocol('WM_DELETE_WINDOW', quitApp)
# boucle principale (à toujours mettre à la fin)
Mafenetre.mainloop() |
Partager