Fenetre.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. # Gestion automatique de l'importation
  2. try :
  3. from tkinter import *
  4. except :
  5. from Tkinter import *
  6. from Outils.Moteur_de_jeu.Plateau import *
  7. from Outils.Moteur_de_jeu.Conversion import *
  8. #####################
  9. # Saisie des noms : #
  10. #####################
  11. def valider_saisie(partie, fenetre, nom_A, nom_B) :
  12. caracteres_autorises = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'+-=_"
  13. nom_A_corrige = ""
  14. if partie.joueurA.est_humain() and nom_A != "" :
  15. for i in range(len(nom_A)) :
  16. if nom_A[i] not in caracteres_autorises :
  17. nom_A_corrige += "_"
  18. else :
  19. nom_A_corrige += nom_A[i]
  20. partie.joueurA.nom = nom_A_corrige
  21. nom_B_corrige = ""
  22. if partie.joueurB.est_humain() and nom_B != "" :
  23. for i in range(len(nom_B)) :
  24. if nom_B[i] not in caracteres_autorises :
  25. nom_B_corrige += "_"
  26. else :
  27. nom_B_corrige += nom_B[i]
  28. partie.joueurB.nom = nom_B_corrige
  29. fenetre.destroy()
  30. partie.lancement()
  31. def saisie_noms(partie) :
  32. fenetre = Tk()
  33. fenetre.title("Quoridor")
  34. fenetre.geometry("500x120+420+300")
  35. config = partie.joueurA.type + partie.joueurB.type
  36. saisie_A = Entry(fenetre)
  37. saisie_B = Entry(fenetre)
  38. bouton = Button(fenetre, text = "Valider", command = lambda : valider_saisie(partie, fenetre, saisie_A.get(), saisie_B.get()))
  39. if config == "HH" :
  40. texte = Label(fenetre, text = "Saisissez vos noms")
  41. texte.pack(padx = 5, pady = 5)
  42. saisie_A.pack(padx = 5, pady = 5)
  43. saisie_B.pack(padx = 5, pady = 5)
  44. elif config == "HO" :
  45. texte = Label(fenetre, text = "Saisissez votre nom")
  46. texte.pack()
  47. saisie_A.pack(padx = 5, pady = 5)
  48. else :
  49. texte = Label(fenetre, text = "Saisissez votre nom")
  50. texte.pack(padx = 5, pady = 5)
  51. saisie_B.pack(padx = 5, pady = 5)
  52. bouton.pack(padx = 5, pady = 5)
  53. fenetre.mainloop()
  54. ####################
  55. #Classe vide initialement dans laquelle seront déclarées deux variables statiques : partie et barriere_en_construction
  56. class Global :
  57. pass
  58. def clic_canevas(clic) : # Quentin 04/10/2016
  59. #Les coordonnées du clic sont accessibles avec clic.x et clic.y
  60. selection = (-1,-1)
  61. bord = Global.partie.affichage.bord
  62. esp = Global.partie.affichage.esp
  63. lg_case = Global.partie.affichage.lg_case
  64. for x in range(Global.partie.plateau.lg) :
  65. for y in range(Global.partie.plateau.ht) :
  66. #Test de collision d'un rectangle dans le cas des cases ou des cercles, selon l'étape du tour
  67. if (Global.partie.etape == "J" and \
  68. clic.x >= (lg_case + esp)*x + bord and clic.x <= (lg_case + esp)*(x+1) + bord - esp and clic.y >= (lg_case + esp)*y + bord and clic.y <= (lg_case + esp)*(y+1) + bord - esp) \
  69. or (Global.partie.etape == "B1" and\
  70. ((lg_case + esp)*(x+1) + bord - esp/2 - 1 - clic.x)**2 + ((lg_case + esp)*(y+1) + bord - esp/2 - 1 - clic.y)**2 <= Global.partie.affichage.Rselect**2) :
  71. selection = (x,y)
  72. barriere_h = Barriere("h",selection[0],selection[1])
  73. barriere_v = Barriere("v",selection[0],selection[1])
  74. h_ok = Global.partie.est_selectionnable(barriere_h)
  75. v_ok = Global.partie.est_selectionnable(barriere_v)
  76. if Global.partie.etape == "J" and Global.partie.joueur_actuel().type == "H" and selection in Global.partie.cases_selectionnables :
  77. Global.partie.executer_tour(Coup("M", case = selection))
  78. Global.partie.affichage.rafraichissement(Global.partie)
  79. elif Global.partie.etape == "B1" and (h_ok or v_ok) :
  80. Global.barriere_en_construction = selection
  81. if h_ok and v_ok : #Si on a le choix entre h et v
  82. Global.partie.etape = "B2"
  83. Global.partie.affichage.rafraichissement(Global.partie)
  84. elif h_ok :
  85. clic_boutonH()
  86. else :
  87. clic_boutonV()
  88. def presser_touche(key) :
  89. if key.char == '*' :
  90. print(code_from_plateau(Global.partie.plateau))
  91. elif Global.partie.etape == "J" and Global.partie.joueur_actuel().type == "O" :
  92. clic_bouton()
  93. def clic_bouton() : # Quentin 04/10/2016
  94. if Global.partie.etape == "J" :
  95. if Global.partie.joueur_actuel().type == "H" :
  96. Global.partie.etape = "B1"
  97. else :
  98. Global.partie.executer_tour( Global.partie.coup_IA() )
  99. elif Global.partie.etape == "B1" :
  100. Global.partie.etape = "J"
  101. elif Global.partie.etape == "B2" :
  102. Global.partie.etape = "B1"
  103. else :
  104. Global.partie.affichage.fenetre.destroy()
  105. Global.partie = Global.partie.relancer()
  106. Global.partie.demarrer()
  107. return
  108. Global.partie.affichage.rafraichissement(Global.partie)
  109. def clic_boutonH() : # Quentin 04/10/2016
  110. Global.partie.executer_tour( Coup("B", barriere = Barriere( "h", Global.barriere_en_construction[0], Global.barriere_en_construction[1]) ) )
  111. Global.partie.affichage.rafraichissement(Global.partie)
  112. def clic_boutonV() : # Quentin 04/10/2016
  113. Global.partie.executer_tour( Coup("B", barriere = Barriere( "v", Global.barriere_en_construction[0], Global.barriere_en_construction[1]) ) )
  114. Global.partie.affichage.rafraichissement(Global.partie)
  115. def clic_case_graphe() :
  116. Global.partie.affichage.rafraichissement(Global.partie)
  117. def clic_case_bouton() :
  118. if Global.partie.joueur_actuel().type == "O" :
  119. clic_bouton()
  120. Global.partie.affichage.rafraichissement(Global.partie)
  121. def clic_regles() :
  122. sous_fenetre = Toplevel()
  123. sous_fenetre.title("Règles du jeu")
  124. texte = Label(sous_fenetre, text = "Vous contrôlez un des deux pions. Votre objectif est d'atteindre le bord opposé du plateau.\nÀ chaque tour, vous devez effectuer une seule de ces deux actions :\n\n-> Se déplacer d'une case horizontalement ou verticalement. Si le pion adverse se situe à côté de vous, vous pouvez sauter par dessus.\nOU\n-> Poser une barrière en travers du chemin de votre adversaire pour le ralentir. La seule contrainte est que vous devez lui laisser au moins un chemin libre vers son objectif.")
  125. texte.grid(row = 0, column = 0, sticky = W)
  126. def afficher_cercle(a,x,y) :
  127. """ Affiche un cercle de sélection en bas à droite de la case (x,y), selon les dimensions renseignées dans a """
  128. a.canevas.create_rectangle((a.lg_case + a.esp)*(x + 1) + a.bord - a.esp/2 - a.Rselect - 1, (a.lg_case + a.esp)*(y + 1) + a.bord - a.esp/2 - a.Rselect - 1,\
  129. (a.lg_case + a.esp)*(x + 1) + a.bord - a.esp/2 + a.Rselect - 1, (a.lg_case + a.esp)*(y + 1) + a.bord - a.esp/2 + a.Rselect - 1, outline = "white", width = 3)
  130. class Affichage :
  131. def __init__(a, plateau, afficher_case_bouton) : # Quentin 17/11/2016
  132. a.bord = 20 #Espace entre le bord du plateau et les cases extrémales
  133. a.esp = 10 #Espace entre les cases
  134. a.lg_case = 50 #Largeur d'une case
  135. a.Rpion = 10 #Rayon des pions
  136. a.Rselect = 8 #Rayon des cercles de sélection
  137. a.ep_select = 2 #Epaisseur du cadre autour de la case du joueur actif
  138. a.Rnoeud = 22 #Rayon des noeuds
  139. a.ep_ar = 4 #Epaisseur des arêtes
  140. a.fenetre = Tk()
  141. a.fenetre.title("Quoridor")
  142. largeur_canevas = (a.lg_case + a.esp) * plateau.lg + a.bord + a.esp
  143. hauteur_canevas = (a.lg_case + a.esp) * plateau.ht + a.bord + a.esp
  144. a.canevas = Canvas(a.fenetre, bg = "#844B16", width = largeur_canevas, height = hauteur_canevas)
  145. a.canevas_graphe = Canvas(a.fenetre, bg = "#999999", width = largeur_canevas, height = hauteur_canevas)
  146. a.var_graphe = IntVar()
  147. a.case_graphe = Checkbutton(a.fenetre, variable = a.var_graphe, text = "Afficher ou masquer le graphe")
  148. a.case_graphe.config(command = clic_case_graphe)
  149. a.case_graphe.grid(row = 4, column = 0, sticky = W)
  150. if afficher_case_bouton :
  151. a.var_bouton = IntVar()
  152. a.case_bouton = Checkbutton(a.fenetre, variable = a.var_bouton, text = "Activer ou désactiver la demande de confirmation")
  153. a.case_bouton.config(command = clic_case_bouton)
  154. a.case_bouton.grid(row = 5, column = 0, sticky = W)
  155. a.canevas.bind("<Button-1>",clic_canevas)
  156. a.canevas.bind("<Key>", presser_touche)
  157. a.canevas.focus_set()
  158. a.texte = Label(a.fenetre,text = "")
  159. a.bouton = Button(a.fenetre,text = "",command = clic_bouton)
  160. a.boutonH = Button(a.fenetre,text = "Horizontalement -",command = clic_boutonH)
  161. a.boutonV = Button(a.fenetre,text = "Verticalement |",command = clic_boutonV)
  162. a.bouton_regles = Button(a.fenetre,text = "Règles du jeu", command = clic_regles)
  163. a.texte_barrieres = Label(a.fenetre, text = "")
  164. a.canevas.grid(row = 0, column = 0, columnspan = 3, padx = 10)
  165. a.texte.grid(row = 1, column = 0, columnspan = 3)
  166. a.texte_barrieres.grid(row = 4, column = 2, rowspan = 2, sticky = E)
  167. a.bouton_regles.grid(row = 4, column = 1, rowspan = 2, padx = 10)
  168. def afficher_canevas(a,partie) : # Quentin 04/10/2016
  169. a.canevas.delete(ALL)
  170. #Cases :
  171. for x in range(partie.plateau.lg) :
  172. for y in range(partie.plateau.ht) :
  173. if partie.plateau.joueur_sur_case(partie.plateau.tour, x, y) :
  174. a.canevas.create_rectangle((a.lg_case + a.esp)*x + a.bord + a.ep_select, (a.lg_case + a.esp)*y + a.bord + a.ep_select,\
  175. (a.lg_case + a.esp)*(x+1) + a.bord - a.esp - a.ep_select + 1, (a.lg_case + a.esp)*(y+1) + a.bord - a.esp - a.ep_select + 1,\
  176. width = a.ep_select, outline = "white", fill = "black")
  177. else :
  178. if (x,y) in partie.cases_selectionnables and partie.etape == "J" :
  179. couleur = "grey"
  180. else :
  181. couleur = "black"
  182. a.canevas.create_rectangle((a.lg_case + a.esp)*x + a.bord, (a.lg_case + a.esp)*y + a.bord, (a.lg_case + a.esp)*(x+1) + a.bord - a.esp, (a.lg_case + a.esp)*(y+1) + a.bord - a.esp,\
  183. width = 0, fill = couleur)
  184. a.canevas.create_rectangle(a.bord, a.bord - 13, a.bord + (a.lg_case + a.esp) * partie.plateau.lg - a.esp, a.bord - 3, width = 0, fill = "#C9660A")
  185. a.canevas.create_rectangle(a.bord, (a.lg_case + a.esp) * partie.plateau.ht - a.esp + a.bord + 3,\
  186. a.bord + (a.lg_case + a.esp) * partie.plateau.lg - a.esp, (a.lg_case + a.esp) * partie.plateau.ht - a.esp + a.bord + 13,\
  187. width = 0, fill = "#EAC019")
  188. for b in partie.plateau.liste_barrieres :
  189. if b.orientation == "h" :
  190. a.canevas.create_rectangle((a.lg_case + a.esp)*b.x + a.bord + 3, (a.lg_case + a.esp)*b.y + a.lg_case + a.bord + 1,\
  191. (a.lg_case + a.esp)*(b.x + 1) + a.bord + a.lg_case - 3, (a.lg_case + a.esp)*(b.y + 1) + a.bord, width = 0,fill = "#FCEBDB")
  192. else :
  193. a.canevas.create_rectangle((a.lg_case + a.esp)*b.x + a.bord + a.lg_case + 1, (a.lg_case + a.esp)*b.y + a.bord + 3,\
  194. (a.lg_case + a.esp)*(b.x + 1) + a.bord, (a.lg_case + a.esp)*(b.y + 1) + a.bord + a.lg_case - 3, width = 0,fill = "#FCEBDB")
  195. #Emplacements libres :
  196. if partie.etape == "B1" :
  197. for b in partie.barrieres_selectionnables :
  198. afficher_cercle(a, b.x, b.y)
  199. #Coin sélectionné :
  200. elif partie.etape == "B2" :
  201. afficher_cercle(a, Global.barriere_en_construction[0], Global.barriere_en_construction[1])
  202. # Affichage des pions :
  203. L = a.bord + a.lg_case//2 # Terme constant
  204. ((x1,y1),(x2,y2)) = partie.plateau.pions
  205. a.canevas.create_rectangle((a.lg_case + a.esp)*x1 + L - a.Rpion, (a.lg_case + a.esp)*y1 + L - a.Rpion,\
  206. (a.lg_case + a.esp)*x1 + L + a.Rpion, (a.lg_case + a.esp)*y1 + L + a.Rpion, fill = "#EAC019")
  207. a.canevas.create_rectangle((a.lg_case + a.esp)*x2 + L - a.Rpion, (a.lg_case + a.esp)*y2 + L - a.Rpion,\
  208. (a.lg_case + a.esp)*x2 + L + a.Rpion, (a.lg_case + a.esp)*y2 + L + a.Rpion, fill = "#C9660A")
  209. def afficher_canevas_graphe(a, partie) : # Quentin 04/10/2016
  210. a.canevas_graphe.delete(ALL)
  211. chemin = path_finding(partie.plateau, partie.plateau.pions[partie.plateau.tour][0], partie.plateau.pions[partie.plateau.tour][1], partie.plateau.rangee_desiree(partie.plateau.tour))
  212. L = a.bord + a.lg_case//2 # Terme constant
  213. #Affichage de toutes les arêtes horizontales :
  214. for x in range(partie.plateau.lg - 1) :
  215. for y in range(partie.plateau.ht) :
  216. a.canevas_graphe.create_line((a.lg_case + a.esp)*x + L, (a.lg_case + a.esp)*y + L,\
  217. (a.lg_case + a.esp)*(x + 1) + L, (a.lg_case + a.esp)*y + L, fill = "black", width = a.ep_ar)
  218. #Affichage de toutes les arêtes verticales :
  219. for x in range(partie.plateau.lg) :
  220. for y in range(partie.plateau.ht - 1) :
  221. a.canevas_graphe.create_line((a.lg_case + a.esp)*x + L, (a.lg_case + a.esp)*y + L,\
  222. (a.lg_case + a.esp)*x + L, (a.lg_case + a.esp)*(y + 1) + L, fill = "black", width = a.ep_ar)
  223. #Effacement des arêtes barrées
  224. for b in partie.plateau.liste_barrieres :
  225. c = "#999999"
  226. if b.orientation == "v" :
  227. a.canevas_graphe.create_line((a.lg_case + a.esp)*b.x + L, (a.lg_case + a.esp)*b.y + L,\
  228. (a.lg_case + a.esp)*(b.x + 1) + L, (a.lg_case + a.esp)*b.y + L, fill = c, width = a.ep_ar)
  229. a.canevas_graphe.create_line((a.lg_case + a.esp)*b.x + L, (a.lg_case + a.esp)*(b.y + 1) + L,\
  230. (a.lg_case + a.esp)*(b.x + 1) + L, (a.lg_case + a.esp)*(b.y + 1) + L, fill = c, width = a.ep_ar)
  231. else :
  232. a.canevas_graphe.create_line((a.lg_case + a.esp)*b.x + L, (a.lg_case + a.esp)*b.y + L,\
  233. (a.lg_case + a.esp)*b.x + L, (a.lg_case + a.esp)*(b.y + 1) + L, fill = c, width = a.ep_ar)
  234. a.canevas_graphe.create_line((a.lg_case + a.esp)*(b.x + 1) + L, (a.lg_case + a.esp)*b.y + L,\
  235. (a.lg_case + a.esp)*(b.x + 1) + L, (a.lg_case + a.esp)*(b.y + 1) + L, fill = c, width = a.ep_ar)
  236. for x in range(partie.plateau.lg) :
  237. for y in range(partie.plateau.ht) :
  238. if partie.plateau.joueur_sur_case(partie.plateau.tour, x, y) :
  239. couleur = "#21C421"
  240. elif (x,y) in chemin :
  241. couleur = "red"
  242. else :
  243. couleur = "#666666"
  244. a.canevas_graphe.create_rectangle((a.lg_case + a.esp)*x + L - a.Rnoeud, (a.lg_case + a.esp)*y + L - a.Rnoeud,\
  245. (a.lg_case + a.esp)*x + L + a.Rnoeud, (a.lg_case + a.esp)*y + L + a.Rnoeud, fill = couleur)
  246. def rafraichissement(a,partie) : # Quentin 17/11/2016
  247. a.afficher_canevas(partie)
  248. apostrophe = partie.joueur_actuel().nom + " : "
  249. a.bouton.grid_forget()
  250. a.boutonH.grid_forget()
  251. a.boutonV.grid_forget()
  252. if partie.etape == "J" :
  253. if not partie.joueur_actuel().est_humain() :
  254. a.bouton.config(text = "Lancer")
  255. a.bouton.grid(row = 2, column = 1)
  256. a.texte.config(text = "Cliquez sur le bouton pour que l'I.A. joue son coup.")
  257. else :
  258. if partie.plateau.barrieres_restantes[partie.plateau.tour] > 0 :
  259. a.bouton.config(text = "Placer une barrière")
  260. a.bouton.grid(row = 2, column = 1)
  261. a.texte.config(text = apostrophe + "Déplacez-vous ou placez une barriere")
  262. else :
  263. a.texte.config(text = apostrophe + "Déplacez-vous")
  264. elif partie.etape == "B1" :
  265. a.bouton.config(text = "Annuler")
  266. a.texte.config(text = apostrophe + "Choisissez l'emplacement du milieu de votre barrière")
  267. a.bouton.grid(row = 2, column = 1)
  268. elif partie.etape == "B2" :
  269. a.bouton.config(text = "Annuler")
  270. a.bouton.grid(row = 2, column = 1)
  271. a.boutonH.grid(row = 3, column = 0)
  272. a.boutonV.grid(row = 3, column = 2)
  273. a.texte.config(text = apostrophe + "Choisissez l'orientation de votre barrière")
  274. else : #"F"
  275. a.bouton.config(text = "Rejouer")
  276. a.bouton.grid(row = 2, column = 1)
  277. gagnant = 1 - partie.plateau.tour
  278. if partie.joueurs[gagnant].est_humain() :
  279. a.texte.config(text = partie.joueurs[gagnant].nom + " a gagné")
  280. else :
  281. a.texte.config(text = "L'I.A. a gagné")
  282. if a.var_graphe.get() == 1 :
  283. a.canevas_graphe.grid(row = 0, column = 4)
  284. a.afficher_canevas_graphe(partie)
  285. else :
  286. a.canevas_graphe.grid_forget()
  287. nb_0 = partie.plateau.barrieres_restantes[0]
  288. nb_1 = partie.plateau.barrieres_restantes[1]
  289. texte = "Joueur jaune : " + str(nb_0) + " barrière"
  290. if nb_0 != 1 :
  291. texte += "s"
  292. texte += "\nJoueur orange : " + str(nb_1) + " barrière"
  293. if nb_1 != 1 :
  294. texte += "s"
  295. a.texte_barrieres.config(text = texte + "\n")
  296. def affichage_sauvage(partie) :
  297. Global.partie = partie
  298. partie.affichage = Affichage(partie.plateau, False)
  299. partie.affichage.rafraichissement(partie)