diff --git a/fil_d_ariane/Cobra/cc_maze.py b/fil_d_ariane/Cobra/cc_maze.py new file mode 100644 index 000000000..6f528a923 --- /dev/null +++ b/fil_d_ariane/Cobra/cc_maze.py @@ -0,0 +1,61 @@ +import tkinter as tk + +SQUARE_SIZE = 20 +COLORS = { + "x": "black", + "-": "white", + "o": "green", + ".": "yellow", + "P": "blue" +} + + +def load_from_file(path) -> (list[list[str]], int, int): + map: list[list[str]] = [] + + with open(path) as file: + for line in file.readlines(): + map.append(list(line.rstrip())) + for i, row in enumerate(map): + for j, char in enumerate(row): + if char == "-": + return map, i, j + return None, -1, -1 + + +def display_grid(canvas, map, PosY: int, PosX: int): + for i in range(len(map)): + for j in range(len(map[0])): + if PosY == i and PosX == j: + color = COLORS["P"] + else: + color = COLORS[map[i][j]] + x0 = j * SQUARE_SIZE + y0 = i * SQUARE_SIZE + x1 = x0 + SQUARE_SIZE + y1 = y0 + SQUARE_SIZE + canvas.create_rectangle(x0, y0, x1, y1, fill=color) + canvas.update() + + +def update_grid(canvas, X, Y, color): + x0 = X * SQUARE_SIZE + y0 = Y * SQUARE_SIZE + x1 = x0 + SQUARE_SIZE + y1 = y0 + SQUARE_SIZE + + canvas.create_rectangle(x0, y0, x1, y1, fill=color) + canvas.update() + + +def init_graphics(map: list[list[str]], PosY, PosX): + width = len(map[0]) * SQUARE_SIZE + height = len(map) * SQUARE_SIZE + window = tk.Tk() + canvas = tk.Canvas(window, width=width, height=height) + + window.title("Participant: Fil d'Ariane") + window.geometry(f"{width}x{height}") + canvas.pack() + display_grid(canvas, map, PosY, PosX) + return window, canvas diff --git a/fil_d_ariane/Cobra/dedale.py b/fil_d_ariane/Cobra/dedale.py index a9a372bc1..47d497f5b 100644 --- a/fil_d_ariane/Cobra/dedale.py +++ b/fil_d_ariane/Cobra/dedale.py @@ -1,137 +1,105 @@ -from tkinter import * +from time import sleep +import cc_maze +import sys -incr = 2 -size = incr * 10 -posX = 1 -posY = 1 -map = [[]] * 100 +DELAY = 0.08 # in seconds -for value in range(0, 100): - map[value] = [0] * 100 +if len(sys.argv) != 2: + print("Invalid arguments:\nPlease enter: python3 dedale.py ") + exit(1) -def checkered(canvas, line_distance): - # vertical lines at an interval of "line_distance" pixel - for x in range(line_distance,canvas_width,line_distance): - canvas.create_line(x * (incr), 0, x * (incr), canvas_height, fill="#476042") - # horizontal lines at an interval of "line_distance" pixel - for y in range(line_distance,canvas_height,line_distance): - canvas.create_line(0, y * (incr), canvas_width, y * (incr), fill="#476042") +map, PosY, PosX = cc_maze.load_from_file(sys.argv[1]) +if map is None: + print("No possible starting point found.") + exit(1) -def right(): - global posX - global posY - if (map[posY][posX + 1] == 1): - return - setACaseXY(posX, posY, 'grey') - map[posY][posX] = -1 - posX += 1 - setACaseXY(posX, posY, 'yellow') - if (map[posY][posX] == 2): - exit(0) - -def left(): - global posX - global posY - if (map[posY][posX - 1] == 1): - return - setACaseXY(posX, posY, 'grey') - map[posY][posX] = -1 - posX -= 1 - setACaseXY(posX, posY, 'yellow') - if (map[posY][posX] == 2): - exit(0) +# Movement def up(): - global posY - global posX - if (map[posY - 1][posX] == 1): - return - setACaseXY(posX, posY, 'grey') - map[posY][posX] = -1 - posY -= 1 - - setACaseXY(posX, posY, 'yellow') - if (map[posY][posX] == 2): - exit(0) - -def down(): - global posY - global posX - if (map[posY + 1][posX] == 1): - return - setACaseXY(posX, posY, 'grey') - map[posY][posX] = -1 - posY += 1 - setACaseXY(posX, posY, 'yellow') - if (map[posY][posX] == 2): - exit(0) + global canvas, map, PosY, PosX + if PosY != 0 and map[PosY - 1][PosX] != "x": + cc_maze.update_grid(canvas, PosX, PosY, "yellow") + map[PosY][PosX] = '.' + PosY -= 1 + cc_maze.update_grid(canvas, PosX, PosY, "blue") + sleep(DELAY) -path = [] - -def algo(value): - if (map[posY][posX + 1] == 0 or map[posY][posX + 1] == 2): - right() - path.append("right") - elif (map[posY + 1][posX] == 0 or map[posY + 1][posX] == 2): - down() - path.append("down") - elif (map[posY][posX - 1] == 0 or map[posY][posX - 1] == 2): - left() - path.append("left") - elif (map[posY - 1][posX] == 0 or map[posY - 1][posX] == 2): - up() - path.append("up") - else: - if (path[-1] == "up"): - down() - elif (path[-1] == "left"): - right() - elif (path[-1] == "down"): - up() - elif (path[-1] == "right"): - left() - path.pop() - - -def setACaseXY(X, Y, color): - points = [X * size, Y * size, size * (X + 1), Y * size, size * (X + 1), size * (Y + 1), X * size, size * (Y + 1)] - w.create_polygon(points, outline="#476042", fill=color, width=4) +def down(): + global canvas, map, PosY, PosX + if PosY != len(map) - 1 and map[PosY + 1][PosX] != "x": + cc_maze.update_grid(canvas, PosX, PosY, "yellow") + map[PosY][PosX] = '.' + PosY += 1 + cc_maze.update_grid(canvas, PosX, PosY, "blue") + sleep(DELAY) -master = Tk() -master.title("Le Fil d'Ariane") -canvas_width = 1280 -canvas_height = 620 -w = Canvas(master, - width=canvas_width, - height=canvas_height) +def left(): + global canvas, map, PosY, PosX + if PosX != 0 and map[PosY][PosX - 1] != "x": + cc_maze.update_grid(canvas, PosX, PosY, "yellow") + map[PosY][PosX] = '.' + PosX -= 1 + cc_maze.update_grid(canvas, PosX, PosY, "blue") + sleep(DELAY) +def right(): + global canvas, map, PosY, PosX + if PosX != len(map[PosY]) - 1 and map[PosY][PosX + 1] != "x": + cc_maze.update_grid(canvas, PosX, PosY, "yellow") + map[PosY][PosX] = '.' + PosX += 1 + cc_maze.update_grid(canvas, PosX, PosY, "blue") + sleep(DELAY) -filepath = 'map.txt' -with open(filepath) as fp: - line = fp.readline() - cnt = 0 - while line: - x = line.find('x') - while x != -1: - setACaseXY(x, cnt, 'red') - map[cnt][x] = 1 - x = line.find('x', x + 1) - x = line.find('o') - if (x != -1): - setACaseXY(x, cnt, 'green') - map[cnt][x] = 2 - line = fp.readline() - cnt += 1 +path = [] -w.pack() -for value in range(0, 1000): - master.after(value * 100, algo, value) +def algorithm(map): + # Votre algorithme va ici. + # Vous pouvez utiliser les fonctions de mouvement top, down, right, left. + # Ces fonctions intéragissent directement avec l'affichage. + # Une case déjà visitée sera transformée en '.' et affichée + # en jaune sur l'écran. + # Good luck! -checkered(w,10) + map_width = len(map[0]) + map_height = len(map) -mainloop() + while map[PosY][PosX] != 'o': + print(map) + if PosX + 1 < map_width and (map[PosY][PosX + 1] == '-' + or map[PosY][PosX + 1] == 'o'): + path.append("right") + right() + elif PosY + 1 < map_height and (map[PosY + 1][PosX] == '-' + or map[PosY + 1][PosX] == 'o'): + path.append("down") + down() + elif PosX - 1 >= 0 and (map[PosY][PosX - 1] == '-' + or map[PosY][PosX - 1] == 'o'): + path.append("left") + left() + elif PosY - 1 >= 0 and (map[PosY - 1][PosX] == '-' + or map[PosY - 1][PosX] == 'o'): + path.append("up") + up() + else: + last_move = path.pop() + if last_move == "right": + left() + elif last_move == "down": + up() + elif last_move == "left": + right() + elif last_move == "up": + down() + + +if __name__ == "__main__": + window, canvas = cc_maze.init_graphics(map, PosY, PosX) + algorithm(map) + window.mainloop() diff --git a/fil_d_ariane/Cobra/requirements.txt b/fil_d_ariane/Cobra/requirements.txt new file mode 100644 index 000000000..5d6fce4a4 --- /dev/null +++ b/fil_d_ariane/Cobra/requirements.txt @@ -0,0 +1 @@ +tkinter diff --git a/fil_d_ariane/Participant/cc_maze.py b/fil_d_ariane/Participant/cc_maze.py new file mode 100644 index 000000000..6f528a923 --- /dev/null +++ b/fil_d_ariane/Participant/cc_maze.py @@ -0,0 +1,61 @@ +import tkinter as tk + +SQUARE_SIZE = 20 +COLORS = { + "x": "black", + "-": "white", + "o": "green", + ".": "yellow", + "P": "blue" +} + + +def load_from_file(path) -> (list[list[str]], int, int): + map: list[list[str]] = [] + + with open(path) as file: + for line in file.readlines(): + map.append(list(line.rstrip())) + for i, row in enumerate(map): + for j, char in enumerate(row): + if char == "-": + return map, i, j + return None, -1, -1 + + +def display_grid(canvas, map, PosY: int, PosX: int): + for i in range(len(map)): + for j in range(len(map[0])): + if PosY == i and PosX == j: + color = COLORS["P"] + else: + color = COLORS[map[i][j]] + x0 = j * SQUARE_SIZE + y0 = i * SQUARE_SIZE + x1 = x0 + SQUARE_SIZE + y1 = y0 + SQUARE_SIZE + canvas.create_rectangle(x0, y0, x1, y1, fill=color) + canvas.update() + + +def update_grid(canvas, X, Y, color): + x0 = X * SQUARE_SIZE + y0 = Y * SQUARE_SIZE + x1 = x0 + SQUARE_SIZE + y1 = y0 + SQUARE_SIZE + + canvas.create_rectangle(x0, y0, x1, y1, fill=color) + canvas.update() + + +def init_graphics(map: list[list[str]], PosY, PosX): + width = len(map[0]) * SQUARE_SIZE + height = len(map) * SQUARE_SIZE + window = tk.Tk() + canvas = tk.Canvas(window, width=width, height=height) + + window.title("Participant: Fil d'Ariane") + window.geometry(f"{width}x{height}") + canvas.pack() + display_grid(canvas, map, PosY, PosX) + return window, canvas diff --git a/fil_d_ariane/Participant/dedale.py b/fil_d_ariane/Participant/dedale.py index 3c891d629..bc19b078f 100644 --- a/fil_d_ariane/Participant/dedale.py +++ b/fil_d_ariane/Participant/dedale.py @@ -1,6 +1,74 @@ -from cc_maze import * +from time import sleep +import cc_maze +import sys + +DELAY = 0.08 # in seconds + +if len(sys.argv) != 2: + print("Invalid arguments:\nPlease enter: python3 dedale.py ") + exit(1) + +map, PosY, PosX = cc_maze.load_from_file(sys.argv[1]) +if map is None: + print("No possible starting point found.") + exit(1) + + +# Movement +def up(): + global canvas, map, PosY, PosX + if PosY != 0 and map[PosY - 1][PosX] != "x": + cc_maze.update_grid(canvas, PosX, PosY, "yellow") + map[PosY][PosX] = '.' + PosY -= 1 + cc_maze.update_grid(canvas, PosX, PosY, "blue") + sleep(DELAY) + + +def down(): + global canvas, map, PosY, PosX + if PosY != len(map) - 1 and map[PosY + 1][PosX] != "x": + cc_maze.update_grid(canvas, PosX, PosY, "yellow") + map[PosY][PosX] = '.' + PosY += 1 + cc_maze.update_grid(canvas, PosX, PosY, "blue") + sleep(DELAY) + + +def left(): + global canvas, map, PosY, PosX + if PosX != 0 and map[PosY][PosX - 1] != "x": + cc_maze.update_grid(canvas, PosX, PosY, "yellow") + map[PosY][PosX] = '.' + PosX -= 1 + cc_maze.update_grid(canvas, PosX, PosY, "blue") + sleep(DELAY) + + +def right(): + global canvas, map, PosY, PosX + if PosX != len(map[PosY]) - 1 and map[PosY][PosX + 1] != "x": + cc_maze.update_grid(canvas, PosX, PosY, "yellow") + map[PosY][PosX] = '.' + PosX += 1 + cc_maze.update_grid(canvas, PosX, PosY, "blue") + sleep(DELAY) + path = [] -def algo(value): - down() \ No newline at end of file + +def algorithm(map): + # Votre algorithme va ici. + # Vous pouvez utiliser les fonctions de mouvement top, down, right, left. + # Ces fonctions intéragissent directement avec l'affichage. + # Une case déjà visitée sera transformée en '.' et affichée + # en jaune sur l'écran. + # Good luck! + pass + + +if __name__ == "__main__": + window, canvas = cc_maze.init_graphics(map, PosY, PosX) + algorithm(map) + window.mainloop() diff --git a/fil_d_ariane/subject/filariane.md b/fil_d_ariane/subject/filariane.md index 5c3047b6b..aee187434 100644 --- a/fil_d_ariane/subject/filariane.md +++ b/fil_d_ariane/subject/filariane.md @@ -1,28 +1,28 @@ ## I. Introduction -Le python est un langage de programmation qui est apparu au début des années 90, il se caractérise par sa structure orientée objet comme le Java mais il est beaucoup plus abordable dans sa syntaxe et il est plus facile d'utilisation pour faire de l’algorithmie ! +Le python est un langage de programmation qui est apparu au début des années 90, il se caractérise par sa structure orientée objet comme le Java mais il est beaucoup plus abordable dans sa syntaxe et il est plus facile d'utilisation pour faire de l’algorithmie ! Il est particulièrement utilisé comme langage pour automatiser des tâches simples, comme un script qui récupérerait la météo sur Internet, ou bien du traitement de données. - -Fun Fact, le nom du langage qui nous intéresse ici vient de l’affection de Guido pour le « Monty Python Flying Circus », une comédie surréaliste créée par un groupe comique anglais « Monty Python ». - + +Fun Fact, le nom du langage qui nous intéresse ici vient de l’affection de Guido pour le « Monty Python Flying Circus », une comédie surréaliste créée par un groupe comique anglais « Monty Python ». + Autre détail amusant, jusqu’en 2018, le créateur du langage Python possédait au sein de la communauté Python le titre de « BDFL » c’est-à-dire de « Benevolent Dictator for Life » ou « Dictateur Bienveillant à Vie ». Cela signifie qu’il tranchait en dernier ressort pour les décisions concernant l’évolution du langage. -![](assets/logo_python.png) +![](assets/logo_python.png) ## II. Consignes -- Pour l’installation veuillez suivre le tutoriel « Installation Python et ses outils ». -- Le nom du repository est : FilAriane_cc. Si cela ne vous dit rien nous vous invitons à lire « le coffre à jouet du petit git ». -- Demandez de l’aide aux Cobras en cas de problème d’installation. Si plus rien ne va, recommencez depuis le début en faisant bien attention à toutes les étapes ! -- Si vous bloquez, rappelez-vous que vous êtes accompagné(e) ! Demandez de l’aide à vos camarades ou à un Cobra. -- Ce document a pour objectif de vous indiquer l’objectif du sujet, mais c’est à vous de trouver l'algorithme. +- Pour l’installation veuillez suivre le tutoriel « Installation Python et ses outils ». +- Le nom du repository est : FilAriane_cc. Si cela ne vous dit rien nous vous invitons à lire « le coffre à jouet du petit git ». +- Demandez de l’aide aux Cobras en cas de problème d’installation. Si plus rien ne va, recommencez depuis le début en faisant bien attention à toutes les étapes ! +- Si vous bloquez, rappelez-vous que vous êtes accompagné(e) ! Demandez de l’aide à vos camarades ou à un Cobra. +- Ce document a pour objectif de vous indiquer l’objectif du sujet, mais c’est à vous de trouver l'algorithme. - Internet est un outil formidable pour découvrir le fonctionnement des choses, servez-vous-en régulièrement ! ## III. Le Fil d’Ariane En tant que mythologicien, vous avez toujours été fasciné par le mythe du fil d’Ariane. Un beau jour, vous avez été envoyé pour résoudre le labyrinthe une bonne fois pour toute. - -Arrivé sur place, vous commencez à avancer dans le labyrinthe tout en posant des balises de repérage. Au bout de plus d’une heure, vous décidez de rebrousser chemin car vous n’avez plus de balise. En vous retournant, vous apercevez des énormes traces de pied et toutes vos balises ont disparu. - -Par chance il vous reste votre téléphone. Servez-vous-en comme GPS pour attendre la sortie. Aucune application n’existe pour cela, vous allez devoir la faire par vous-même ! + +Arrivé sur place, vous commencez à avancer dans le labyrinthe tout en posant des balises de repérage. Au bout de plus d’une heure, vous décidez de rebrousser chemin car vous n’avez plus de balise. En vous retournant, vous apercevez des énormes traces de pied et toutes vos balises ont disparu. + +Par chance il vous reste votre téléphone. Servez-vous-en comme GPS pour attendre la sortie. Aucune application n’existe pour cela, vous allez devoir la faire par vous-même ! Le but du projet est donc de résoudre un labyrinthe à l’aide d’un algorithme. Pour cela vous allez devoir continuer le code du fichier « dedale.py ». @@ -30,75 +30,74 @@ Pour cela vous allez devoir continuer le code du fichier « dedale.py ». ![](assets/minotaure.png) L’objectif est de faire un algorithme le plus rapide possible. Il n’y a pas vraiment d'intérêt à rentrer le chemin en dur. - + Soyez créatif ! Si vous voulez aller plus loin, vous pouvez essayer de le faire par vous-même, sinon il en existe plusieurs assez simple de disponible sur internet comme le **« A* »** ou le **« Dijkstra »**. ### Droit dans le mur Avant de commencer, vous devez avoir avec votre sujet 2 fichiers en plus. - -- **map.txt** : C’est la carte de votre labyrinthe, les « x » représentent les murs, les « - » les chemins et le « o » la sortie. Vous devez aussi savoir que vous commencerez toujours en haut à gauche du labyrinthe. + +- **map.txt** : C’est la carte de votre labyrinthe, les « x » représentent les murs, les « - » les chemins et le « o » la sortie. Vous devez aussi savoir que vous commencerez toujours en haut à gauche du labyrinthe. - **dedale.py** : C’est le fichier dans lequel vous allez implémenter votre algorithme. - + Cela étant dit, vous pouvez tester votre programme en écrivant dans votre terminal : ```sh -python3 dedale.py +python3 dedale.py ``` -Si tout se passe bien, vous devriez avoir une fenêtre comme celle-ci : +Si tout se passe bien, vous devriez avoir une fenêtre comme celle-ci : ![](assets/window.png) -### LabyTips & LabyTrics - +### LabyTips & LabyTrics + Bon cela étant, votre algo ne fait pas grand-chose pour le moment. Pour l’améliorer, vous devez remplir la fonction « algo ». Vous pouvez appeler les fonctions « right », « down », « left » et « up » pour vous diriger. - + Avant de vous lancer dans votre algorithme, vous devez avoir en tête les points ci-dessous : - -- Vous avez accès à une variable « map » qui contient toutes les valeurs à jour de la carte. -- Vous avez aussi accès aux variables « posX » et « posY » qui vous donne votre position en les utilisant comme ceci : « map[posY][posX] » (ces variables sont mises à jour automatiquement). -- Les valeurs de la map sont : « x » = 1 / « - » = 0 / « o » = 2 / -1 pour les cases déjà visitée. -- La fonction algo est appelée en boucle jusqu’à que « map[posY][posX] » soit égale à 2, donc la sortie. -- L’affichage est mis à jour à chaque fois que la fonction algo est finie. -- La variable « value » envoyée en paramètre dans la fonction algo ne sert qu’à compter le nombre de fois que la fonction algo est appelée. Elle peut être utile une fois l’algo terminé. -- Une variable « path » est mise à disposition. Vous connaîtrez son utilité dans la partie suivante. + +- Vous avez accès à une variable « map » qui contient toutes les valeurs à jour de la carte. +- Vous avez aussi accès aux variables « posX » et « posY » qui vous donne votre position en les utilisant comme ceci : « map[posY][posX] » (ces variables sont mises à jour automatiquement). +- Les valeurs de la map sont : « x » = 1 / « - » = 0 / « o » = 2 / -1 pour les cases déjà visitée. +- La fonction algo est appelée en boucle jusqu’à que « map[posY][posX] » soit égale à 2, donc la sortie. +- L’affichage est mis à jour à chaque fois que la fonction algo est finie. +- La variable « value » envoyée en paramètre dans la fonction algo ne sert qu’à compter le nombre de fois que la fonction algo est appelée. Elle peut être utile une fois l’algo terminé. +- Une variable « path » est mise à disposition. Vous connaîtrez son utilité dans la partie suivante. Veillez à ne faire qu’une action à chaque appel de la fonction « algo ». -### En route vers la sortie - - +### En route vers la sortie + + Pour bien commencer essayez de changer la fonction « down » par « right » dans la fonction et voyez ce qu’il se passe. - -Une fois cela fait, faites une condition basique pour faire tourner votre personnage lorsqu’il se bloque dans un coin. - + +Une fois cela fait, faites une condition basique pour faire tourner votre personnage lorsqu’il se bloque dans un coin. + Enfin, vous pouvez vous aider de la variable « path » pour sauvegarder le chemin emprunté et donc pouvoir revenir en arrière si besoin. **À vous de jouer !** ![](assets/example.png) -## IV. Le bout du tunnel - +## IV. Le bout du tunnel + Félicitations, vous avez un algorithme fonctionnel. Vous allez pouvoir partir à l'aventure ! Maintenant que vous avez votre GPS pour labyrinthe vous allez pouvoir le continuer pour l'améliorer. -Voici quelques petits exemples d’amélioration : -- Modifier la carte pour mettre votre algorithme à rude épreuve. -- Essayez de l’optimiser pour qu’il soit plus rapide. -- Vous pouvez faire de la gestion d’erreurs. (Vérifier que le labyrinthe a bien un début et une fin par exemple). -- Créer un générateur de labyrinthe pour tester votre algorithme. +Voici quelques petits exemples d’amélioration : +- Modifier la carte pour mettre votre algorithme à rude épreuve. +- Essayez de l’optimiser pour qu’il soit plus rapide. +- Vous pouvez faire de la gestion d’erreurs. (Vérifier que le labyrinthe a bien un début et une fin par exemple). +- Créer un générateur de labyrinthe pour tester votre algorithme. Si le labyrinthe à plusieurs chemins possible, trouvez le chemin le plus court. - ->:info !icon:circle-info Si vous êtes curieux, pensez à poser vos questions aux Cobras. Ils seront ravis de partager leurs connaissances avec vous. - - - + +>:info !icon:circle-info Si vous êtes curieux, pensez à poser vos questions aux Cobras. Ils seront ravis de partager leurs connaissances avec vous. + + + + + + - - - - \ No newline at end of file