236 lines
6.1 KiB
Python
236 lines
6.1 KiB
Python
|
from lib.maze import gen_maze
|
||
|
from lib.pile import Pile
|
||
|
from random import shuffle
|
||
|
from tkinter import Canvas, Tk, Button
|
||
|
import tkinter.messagebox
|
||
|
from time import time
|
||
|
|
||
|
|
||
|
def find_maze_start(maze: list) -> tuple:
|
||
|
"""
|
||
|
Find the coo of the maze's entrance.
|
||
|
In maze: list
|
||
|
Out: tuple
|
||
|
"""
|
||
|
maze_end, mazex = len(maze), len(maze[0])
|
||
|
for i in range(maze_end):
|
||
|
for l in range(mazex):
|
||
|
if maze[i][l] == ">":
|
||
|
return (l, i)
|
||
|
|
||
|
# si le labyrinthe n'a pas d'entree
|
||
|
tkinter.messagebox.showinfo(
|
||
|
title="Amaze!", message="Il y a des erreurs dans le labyrinthe!"
|
||
|
)
|
||
|
raise Exception("Il y a des erreurs dans le labyrinthe!")
|
||
|
return (-1, -1)
|
||
|
|
||
|
|
||
|
def find_available_moves(
|
||
|
curr_x: int, curr_y: int, sizex: int, sizey: int, maze: list
|
||
|
) -> list:
|
||
|
"""
|
||
|
renvoit les coordonnees possible pour certain x et y
|
||
|
In curr_x, curry, sizex, sizey, maze: int, int, int, int, list
|
||
|
Out: list
|
||
|
"""
|
||
|
moves = [
|
||
|
(curr_x - 1, curr_y),
|
||
|
(curr_x + 1, curr_y),
|
||
|
(curr_x, curr_y - 1),
|
||
|
(curr_x, curr_y + 1),
|
||
|
]
|
||
|
return [
|
||
|
(x, y)
|
||
|
for x, y in moves
|
||
|
if 0 < x < sizex and 0 < y < sizey and maze[y][x] in [" ", "O"]
|
||
|
]
|
||
|
|
||
|
|
||
|
def rectangle(
|
||
|
x: int, y: int, taille_cells: int, couleur: str, canvas: Canvas, *, cailloux=None
|
||
|
) -> Pile:
|
||
|
"""
|
||
|
cree un carre au coordonnees x et y
|
||
|
In x, y, taille_cells, couleur, canvas, cailloux = int, int, int, str, Canvas(), Pile()
|
||
|
Out cailloux: Pile()
|
||
|
"""
|
||
|
if cailloux == None:
|
||
|
canvas.create_rectangle(
|
||
|
(x * taille_cells) - taille_cells / 2,
|
||
|
(y * taille_cells) - taille_cells / 2,
|
||
|
((x + 1) * taille_cells) - taille_cells / 2,
|
||
|
((y + 1) * taille_cells) - taille_cells / 2,
|
||
|
width=0,
|
||
|
fill=couleur,
|
||
|
tags=("path",),
|
||
|
)
|
||
|
else:
|
||
|
cailloux.empiler(
|
||
|
canvas.create_rectangle(
|
||
|
(x * taille_cells) - taille_cells / 2,
|
||
|
(y * taille_cells) - taille_cells / 2,
|
||
|
((x + 1) * taille_cells) - taille_cells / 2,
|
||
|
((y + 1) * taille_cells) - taille_cells / 2,
|
||
|
width=0,
|
||
|
fill=couleur,
|
||
|
tags=("path",),
|
||
|
)
|
||
|
)
|
||
|
return cailloux
|
||
|
|
||
|
|
||
|
def win(
|
||
|
x: int, y: int, taille_cells: int, start: int, canvas: Canvas, button: Button
|
||
|
) -> None:
|
||
|
"""
|
||
|
gere la fin du programme, quand la tete trouve la fin du labyrinthe.
|
||
|
In x, y, taille_cells, start, canvas, button: int, int, int, int, Canva(), Button()
|
||
|
Out: None
|
||
|
"""
|
||
|
# reactive le bouton de resolution
|
||
|
button["state"] = "active"
|
||
|
|
||
|
# affiche un carre vert sur la fin du labyrinthe
|
||
|
rectangle(x, y, taille_cells, "green", canvas)
|
||
|
|
||
|
# calcule le temps
|
||
|
end = time()
|
||
|
seconds = round(end) - round(start)
|
||
|
heures, minutes = 0, 0
|
||
|
while seconds > 59:
|
||
|
minutes += 1
|
||
|
seconds -= 60
|
||
|
if minutes > 59:
|
||
|
heures += 1
|
||
|
minutes -= 60
|
||
|
if minutes > 0:
|
||
|
m = f"{minutes}min "
|
||
|
else:
|
||
|
m = ""
|
||
|
if heures > 0:
|
||
|
h = f"{heures}h "
|
||
|
else:
|
||
|
h = ""
|
||
|
|
||
|
# affiche le temps
|
||
|
tkinter.messagebox.showinfo(
|
||
|
title="Amaze!", message=f"Labyrinthe résolu en {h}{m}{seconds}s!"
|
||
|
)
|
||
|
|
||
|
return None
|
||
|
|
||
|
|
||
|
def delete_old_path(canvas: Canvas) -> None:
|
||
|
"""
|
||
|
reset l'ancien chemin.
|
||
|
In: canvas: Canvas()
|
||
|
Out: None
|
||
|
"""
|
||
|
items = canvas.find_all()
|
||
|
|
||
|
for item_id in items:
|
||
|
tags = canvas.gettags(item_id)
|
||
|
if "path" in tags:
|
||
|
canvas.delete(item_id)
|
||
|
return None
|
||
|
|
||
|
|
||
|
def resolve(
|
||
|
maze: list,
|
||
|
canvas: Canvas,
|
||
|
root: Tk,
|
||
|
taille_cells: int,
|
||
|
*,
|
||
|
button=None,
|
||
|
poucet=None,
|
||
|
x=None,
|
||
|
y=None,
|
||
|
cailloux=None,
|
||
|
start=None,
|
||
|
) -> None:
|
||
|
"""
|
||
|
Resout le labyrinthe, compte le temps de resolution et grise le bouton de resolution
|
||
|
In :
|
||
|
maze (list)
|
||
|
canvas (Canvas())
|
||
|
root (Tk())
|
||
|
taille_cells(int)
|
||
|
button (Button())
|
||
|
poucet (Pile())
|
||
|
x (int)
|
||
|
y (int)
|
||
|
cailloux (Pile())
|
||
|
start (int)
|
||
|
Out :
|
||
|
None
|
||
|
"""
|
||
|
if poucet != None and poucet.est_vide():
|
||
|
try:
|
||
|
find_available_moves(x, y, maze) == []
|
||
|
except:
|
||
|
button["state"] = "active"
|
||
|
tkinter.messagebox.showinfo(
|
||
|
title="Amaze!", message=f"Labyrinthe impossible!"
|
||
|
)
|
||
|
del poucet, cailloux, x, y, start, maze
|
||
|
return None
|
||
|
|
||
|
if poucet == None: # initialisation
|
||
|
delete_old_path(canvas)
|
||
|
button["state"] = "disabled"
|
||
|
start = time()
|
||
|
x, y = find_maze_start(maze)
|
||
|
rectangle(x, y, taille_cells, "black", canvas)
|
||
|
sizex, sizey = len(maze[0]), len(maze)
|
||
|
poucet = Pile()
|
||
|
cailloux = Pile()
|
||
|
|
||
|
sizex, sizey = len(maze[0]), len(maze)
|
||
|
suiv = find_available_moves(x, y, sizex, sizey, maze)
|
||
|
|
||
|
if suiv != []: # si on peut avancer
|
||
|
shuffle(suiv)
|
||
|
x, y = suiv[0][0], suiv[0][1]
|
||
|
|
||
|
if maze[y][x] == "O":
|
||
|
win(x, y, taille_cells, start, canvas, button)
|
||
|
del poucet, cailloux, x, y, start, maze
|
||
|
return None
|
||
|
|
||
|
maze[y][x] = "V"
|
||
|
poucet.empiler((x, y))
|
||
|
cailloux = rectangle(x, y, taille_cells, "red", canvas, cailloux=cailloux)
|
||
|
|
||
|
else: # sinon on recule
|
||
|
coo = poucet.depiler()
|
||
|
x, y = coo[0], coo[1]
|
||
|
|
||
|
next_suiv = find_available_moves(x, y, sizex, sizey, maze)
|
||
|
for x2, y2 in next_suiv:
|
||
|
if maze[y][x] == "O":
|
||
|
win(x, y, taille_cells, end, canvas, button)
|
||
|
del poucet, cailloux, x, y, start, maze
|
||
|
return None
|
||
|
if next_suiv == []:
|
||
|
edit = cailloux.depiler()
|
||
|
canvas.itemconfig(edit, fill="#a6a6a6")
|
||
|
else:
|
||
|
poucet.empiler((x, y))
|
||
|
|
||
|
root.after(
|
||
|
5,
|
||
|
lambda: resolve(
|
||
|
maze,
|
||
|
canvas,
|
||
|
root,
|
||
|
taille_cells,
|
||
|
poucet=poucet,
|
||
|
x=x,
|
||
|
y=y,
|
||
|
cailloux=cailloux,
|
||
|
start=start,
|
||
|
button=button,
|
||
|
),
|
||
|
)
|