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
| from tkinter import*
import random
INCONNU = -1
PERDU = -2
DRAPEAU = -3
QUESTION = -4
######### à réaliser
def genere_plateau(largeur,hauteur,probabilite_mine):
"""Génère un plateau de jeu de taille donnée."""
plateau = []
for i in range(largeur):
plateau.append([])
for j in range(hauteur):
plateau[i].append( { "mine" : False,
"etat" : INCONNU } )
return(plateau)
def total_mines(plateau):
"""Compte le nombre total de mines sur le plateau."""
return 0
def cases_voisines(plateau,x,y):
"""Donne la liste des cases voisines de la case "(x,y)"."""
return []
def compte_mines_voisines(plateau,x,y):
"""Compte le nombre de mines voisines de la case "(x,y)" sur le plateau
"plateau"."""
return 0
def composante_connexe(plateau,x,y):
"""Met le plateau à jour en ouvrant toutes les cases vides à partir de la
case "(x,y)"""
def dans_plateau(plateau,x,y,clic):
global detection_clic_sur_objet
x=clic.x// (largeur_case+1)
y=clic.y// (largeur_case+1)
print(x,y)
if(0<=x<=largeur and 0<=y<=hauteur):
dans_plateau=True
else:
dans_plateau=False
if (dans_plateau):
print ("ok")
return
##########
def decouvre_case(plateau,x,y):
"""Découvre une case sur le plateau. Le plateau est mis à jours en
découvrant toute la composante connexe de la case "(x,y)", et la fonction
renvoie un booléen pour dire si la case "(x,y)" était une mine ou pas.
"""
if plateau[x][y]["mine"]:
plateau[x][y]["etat"] = PERDU
print("OUPS... La case ({},{}) contenait une mine !".format(x,y))
return False
composante_connexe(plateau,x,y)
return True
def dessine_case(plateau,x,y,solution=False):
"""Dessine la case "(x,y)" sur le plateau.
Si "solution" est vraie, dessine aussi les mines qui sont dans des cases
fermées."""
x1 = x*(largeur_case+1)+2
y1 = y*(hauteur_case+1)+2
x2 = (x+1)*(largeur_case+1)
y2 = (y+1)*(hauteur_case+1)
etat = plateau[x][y]["etat"]
if etat == 0:
grille.create_rectangle(x1,y1,x2,y2,outline='#c0c0c0',fill='#c0c0c0')
elif 0 < etat < 9:
grille.create_rectangle(x1,y1,x2,y2,outline='#c0c0c0',fill='#c0c0c0')
x1 = x1 + largeur_case//2
y1 = y1 + hauteur_case//2
grille.create_text(x1,y1,justify=CENTER,text=str(etat))
elif etat == DRAPEAU:
grille.create_image(x1,y1,image=drapeau_img,anchor=NW)
elif etat == QUESTION:
grille.create_image(x1,y1,image=question_img,anchor=NW)
elif etat == INCONNU:
if plateau[x][y]["mine"] and solution:
grille.create_image(x1,y1,image=mine_img,anchor=NW)
else:
grille.create_image(x1,y1,image=inconnu_img,anchor=NW)
elif etat == PERDU:
grille.create_image(x1,y1,image=perdu_img,anchor=NW)
else:
assert(False)
def dessine_plateau(plateau,solution=False):
l = len(plateau)
h = len(plateau[0])
grille.delete(ALL)
for x in range(l):
for y in range(h):
dessine_case(plateau,x,y,solution)
def __action_clic(clic):
"""Fonction appelée quand on fait un clic sur la fenêtre."""
# clic.x et clic.y contiennent les coordonnées, en pixel,
# du clic à l'intérieur de la fenêtre
x = clic.x // (largeur_case+1) # x et y contiennent les
y = clic.y // (hauteur_case+1) # coordonnées de la case
if not dans_plateau(plateau_courant,x,y,clic):
return
if plateau_courant[x][y]["etat"] != INCONNU:
print ("ok")
ok = decouvre_case(plateau_courant,x,y)
dessine_plateau(plateau_courant)
return
def __action_m(e):
"""Permet d'afficher la solution pendant 1 seconde."""
import copy
from time import sleep
p = copy.deepcopy(plateau_courant)
compte_mines_solution(p)
dessine_plateau(p,True)
grille.update_idletasks()
sleep(1)
dessine_plateau(plateau_courant)
def __action_q(e):
"""Permet de quitter le jeux."""
root.destroy()
#quelques variables globales, modifiable par l'utilisateur
largeur = 54 # largeur du plateau, en nombre de cases
hauteur = 18 # hauteur du plateau, en nombre de cases
probabilite_mine = 0.15 # probabilité qu'une case contienne une mine
#fenêtre principale
root = Tk()
root.title("Démineur")
root.resizable(width=False, height=False)
Label(text="démineur en Python").pack()
#les images utilisées pour les cases spéciales
mine_img = PhotoImage(file="mine.gif")
perdu_img = PhotoImage(file="mine_perdu.gif")
drapeau_img = PhotoImage(file="drapeau.gif")
mauvais_drapeau_img = PhotoImage(file="mauvais_drapeau.gif")
question_img = PhotoImage(file="interogation.gif")
inconnu_img = PhotoImage(file="inconnu.gif")
# on vérifie que les images ont toute les même dimensions
assert (mine_img.height() == perdu_img.height()
== drapeau_img.height()
== mauvais_drapeau_img.height()
== question_img.height()
== inconnu_img.height())
assert (mine_img.width() == perdu_img.width()
== drapeau_img.width()
== mauvais_drapeau_img.width()
== question_img.width()
== inconnu_img.width())
largeur_case = mine_img.width()
hauteur_case = mine_img.height()
# la grille : un objet de type "Canvas" pour pouvoir dessiner dedans.
grille = Canvas(root, width = largeur*(largeur_case+1)+1,
height = hauteur*(hauteur_case+1)+1,
bg = "#7f7f7f")
grille.pack()
# les évènements à gérer
root.bind("q", __action_q)
root.bind("m", __action_m)
grille.bind("<Button-1>", __action_clic)
# création du plateau, et début du programme...
plateau_courant = genere_plateau(largeur,hauteur,probabilite_mine)
dessine_plateau(plateau_courant)
grille.mainloop()
### Fin du fichier ###
###################### |
Partager