PYTHON : PROJETS 2025

Tous les projets proposés sur cette page mettent en oeuvre la réalisation d'une application complète, qui inclut à la fois des entrées/sorties sur fichier (par exemple pour stocker la configuration d'un jeu ou le tableau des meilleurs scores) et une interface homme/machine pilotée au clavier et/ou à la souris. Ces projets vont donc nécessairement avoir besoin d'un certain nombre de modules de la bibliothèque standard fournie avec le langage Python.

Avant de commencer, il est donc très utile de bien étudier et comprendre l'ensemble des codes sources fournis dans les exemples vus en cours, ainsi que dans les solutions des exercices vus en TD, qui fournissent des points de départ pour le code à réaliser. En particulier, l'utilisation des modules ezCLI et ezTK est OBLIGATOIRE car cela va vous permettre de gagner beaucoup de temps sur la réalisation et la finalisation du code. Pour chacun des sujets, sont indiqués les exemples et les exercices qui pourront vous servir de point de départ.

A partir de la semaine 19 (5 mai), la moitié créneaux de TD seront exclusivement consacrés au suivi du projet de programmation. Il est donc primordial que les 2 membres du binôme soient présents simultanément. Si les 2 membres du binôme ne sont pas officiellement dans le même groupe de TD, on organisera une permutation spécifique pour les créneaux concernés, en fonction du nombre de binômes concernés. La présence à ces séances de suivi est OBLIGATOIRE et toute absence non justifiée sera fortement sanctionnée par une pénalité d'un tiers par absence sur la note finale du projet (coefficient 0.66 pour une absence, 0.33 pour deux et 0 pour trois).

Projet 1 : Rush

Ecrire un programme rush qui implémente une variante du jeu Rush Hour, disponible sur différents sites web ainsi que sur téléphone Android ou iOS (sous les noms "Rush Hour", "No Parking", "Traffic Rush" ou "Traffic Jam"). Le jeu se joue sur une grille 6x6 simulant un parking où se trouve des voitures (rectangles de 2 cases alignées) ou des camions (rectangles de 3 cases alignées). L'objectif du joueur est de faire sortir la voiture rouge du parking en déplaçant les autres véhicules (en avant ou en arrière) pour ménager un chemin vers la porte de sortie.

Dans la variante demandée pour ce projet, le graphisme est simplifié à l'extrême en définissant de simples cases de couleur pour identifier les différents véhicules (cf. image ci-dessous), mais évidemment rien ne vous interdit de mettre en oeuvre une visualisation plus élaborée. Le haut de la fenêtre affiche une zone d'information avec les 3 paramètres du jeu : le numéro du niveau en cours, le nombre de déplacements effectués pour ce niveau, et le score courant du joueur. Le jeu devra se piloter à la souris selon les mêmes modalités que la version présentée dans le lien ci-dessus: cliquer sur l'extrémité d'un véhicule le fait avancer d'une case dans cette direction. Pour chaque niveau, le programme devra détecter le moment où le chemin vers la sortie est dégagé pour la voiture rouge, et lancer une animation qui déplacera automatiquement la voiture pour la faire sortir du parking.


Le jeu utilise un principe de score décroissant pour évaluer les performances du joueur. Au départ, le joueur possède 9999 points et chaque déplacement d'une case pour un véhicule, lui fait perdre un point. L'objectif est d'arriver au bout des 40 niveaux du jeu en ayant consommé un nombre minimal de points de déplacement. De manière optionnelle, on pourra également rajouter un mécanisme de renoncement : si le joueur n'arrive pas à finir un niveau, il peut cliquer sur la ligne de score en haut de la fenêtre, pour passer directement au niveau suivant, en acceptant de prendre ainsi 100 ou 200 points de pénalité.

Pour simplifier le développement du programme, on fournit une archive rush.zip qui contient un fichier CSV regroupant 40 grilles classées par niveau de difficulté, ainsi qu'un fichier squelette rushZ.py qui pourra servir de point de départ pour l'implémentation. La lecture du fichier CSV et sa conversion en un tableau de chaînes de caractères sont déjà inclus dans le squelette.

Exemples à relire avant de commencer le projet :
  1. Exemple C6B_event.py et Exercice C5A_leapfrog.py (pour la gestion des clicks de la souris)
  2. Exemple C4C_random.py (pour l'utilisation de la widget Entry)
  3. Exemple C2C_toggle.py (pour la mise en oeuvre de l'animation de la voiture rouge)
  4. Exemple B4A_csvfile.py et Exercice C6A_maze.py (pour la lecture des fichiers CSV)

Projet 2 : Flood

Ecrire un programme Flood qui implémente une variante à 2 joueurs du jeu Food-It, disponible sur différents sites web ainsi que sur téléphone Android ou iOS. Dans le jeu standard à 1 joueur, l'objectif est de colorier l'intégralité de la grille en une couleur unique, en partant du coin supérieur gauche et en inondant toutes les cases connexes de la même couleur. A 2 joueurs, le jeu se transforme en une conquête territoriale, où l'objectif de chaque joueur est d'être le premier à colorier plus de la moitié de la grille de jeu, en partant de sa case de départ : coin supérieur gauche pour le joueur A, coin inférieur droit pour le joueur B.

La figure ci-dessous fournit un exemple possible pour l'interface graphique du programme. Dans un premier temps, on affiche une fenêtre de configuration (cf. à gauche de la figure) permettant de saisir les différents paramètres du jeu (noms des joueurs, taille de la grille, nombre de couleur pour les cases). Puis, lorsque le joueur clique sur le bouton 'START', la fenêtre de configuration est remplacée par la fenêtre principale du jeu (cf. à droite de la figure), qui se compose de 3 zones : la zone centrale montre la grille de jeu, commune aux 2 joueurs, et les zones droite et gauche affichent les informations relatives à chaque joueur.

Pour effectuer le choix des couleurs à utiliser à chaque coup, les 2 joueurs se partagent le clavier : le joueur A utilise la partie gauche du clavier (touches A,Z,E,R,Q,S,D,F) et le joueur B, la partie droite (touches U,I,O,P,J,K,L,M). Un aide-mémoire est affiché sur la zone de chaque joueur pour lui rappeler les couleurs associées aux différentes touches qui le concerne. De même, la progression de la partie est visualisée en affichant le nombre de coups joués, ainsi que le score courant pour chacun des 2 joueurs (correspondant au nombre de cases coloriées lors du dernier coup).

Une caractéristique importante du jeu est que la partie ne se déroule pas en mode tour-par-tour, mais en mode temps-réel, donc rien n'interdit à un joueur d'effectuer rapidement plusieurs coups d'affilée sans que l'adversaire ne joue. Néanmoins, un joueur n'a droit qu'à un nombre limité de coups pour chaque partie (ce nombre est calculé en fonction de la taille de la grille et du nombre de couleurs). Lorsque la réserve de coups d'un joueur est épuisée, l'adversaire peut continuer à jouer pour augmenter sa conquête territoriale. A l'inverse, le jeu se bloque dès que l'un des joueurs a réussi à colorier plus de la moitié des cases de la grille, et le programme affiche le vainqueur de la partie.

De manière optionnelle, on peut également intégrer dans le programme, un mécanisme de sauvegarde/récupération des parties jouées. Pour cela, l'idéal est d'utiliser un fichier au format INI tel qu'on l'a vu en cours. Il n'y a pas de directives spécifiques pour le format exact de ce fichier, à vous d'imaginer un formalisme permettant de stocker et récupérer facilement toutes les informations d'une partie donnée (date et heure, noms des joueurs, taille de la grille, nombre de couleurs, liste des coups joués et score final)

Pour simplifier le développement du programme, on fournit une archive flood.zip qui contient un fichier squelette floodZ.py qui pourra servir de point de départ pour l'implémentation.

Exemples à relire avant de commencer le projdet :
  1. Page Wikipedia concernant le remplissage par diffusion qui est l'algorithme principal à implémenter pour effectuer le changement de couleur des cases.
  2. Exemple C5C_win.py (pour l'alternance entre fenêtre de configuration et fenêtre de jeu)
  3. Exemple C2C_toggle.py (pour le changement d'état automatique des case de la grille)
  4. Exemple C6D_event.py et Exercice C6A_slide.py (pour la gestion des touches du clavier)
  5. Exemple B5A_inifile.py et B6_scores.py (pour la lecture/écriture des fichiers INI)

Projet 3 : Bridges

Ecrire un programme bridges qui implémente le jeu de connexions, originaire du Japon, sous le nom de Hashiwokakero (cf. cette page Wikipedia pour avoir toutes les informations sur les règles du jeu). L'objectif du joueur est de connecter l'ensemble des îles placées sur une grille, en construisant le nombre exact de ponts indiqué pour chaque île. Une version jouable en ligne se trouve sur ce site et permet de se familiariser au mécanisme du jeu avec des exemples de complexité variable.

Dans la version originale, chaque île ne peut être connectée que par 1 ou 2 ponts avec chacune de ses 4 îles voisines (N, E, S, W). Pour augmenter la difficulté du jeu, la variante implémentée pour ce sujet autorise 1, 2 ou 3 ponts dans chacune des 4 directions, mais en imposant un nombre maximal de 9 ponts pour chacune des îles. De plus, pour simplifier la fonction d'affichage, on ne visualise les ponts que par un seul segment entre deux îles, mais dont l'épaisseur sera variable (trait fin pour un pont simple, trait moyen pour un pont double, trait épais pour un pont triple). La figure ci-dessous fournit un exemple possible pour l'interface graphique du programme, dans lequel on peut voir les 3 épaisseurs des ponts reliant les îles.

L'interaction entre le programe et le joueur s'effectue uniquement à l'aide de la souris. Lorsque le joueur clique sur une première île, celle-ci devient "active" (ce qui sera symbolisé par un changement de couleur du disque associé à l'île), puis en cliquant sur une des îles voisines, un pont sera créé avec un segment d'une épaisseur variable selon le nombre de clics. Si le joueur réalise qu'il s'est trompé, il peut détruire un pont entre 2 îles en cliquant avec le bouton droit au lieu du bouton gauche. Au fur et à mesure de la création ou destruction des ponts, les compteurs sur les îles sont décrémentés ou incrémentés. Par conséquent, lorsque tous les compteurs tombent à la valeur 0, le niveau est considéré comme résolu et le programme doit afficher le niveau suivant.

Pour simplifier le développement du programme, on fournit une archive bridges.zip qui contient un fichier CSV regroupant 1000 grilles de taille variable, classées par niveau de difficulté, ainsi qu'un fichier squelette bridgesZ.py qui pourra servir de point de départ pour l'implémentation. La lecture du fichier CSV et sa conversion en un tableau de listes sont déjà inclus dans le squelette.

Exemples à relire avant de commencer le projet :
  1. Exemple C7A_canvas.py (pour l'utilisation générale de la widget Canvas)
  2. Exemple C7D_canvas.py (pour la détection des éléments cliqués dans un Canvas)
  3. Exemple B4A_csvfile.py et Exercice C6A_maze.py (pour la lecture des fichiers CSV)

Projet 4 : Automates cellulaires

Ecrire un programme autocell qui permet de visualiser de manière graphique, l'évolution temporelle de différents modèles d'automates cellulaires. Les automates cellulaires constituent les structures les plus simples utilisés pour les algorithmes de simulation de "vie artificielle" (cf. cette page Wikipedia pour avoir des informations sur les principes de mise en oeuvre, ainsi que sur les différents modèles proposés dans ce contexte). Parmi ces modèles, le Jeu de la Vie, inventé en 1970 par le mathématicien John Conway, est sans conteste l'automate cellulaire le plus célèbre. L'ensemble de ses caractéristiques sont présentés de manière extrêmement détaillée sur le site conwaylife.com.

Un automate cellulaire est généralement défini sur une grille 2D, dans laquelle chaque cellule de la grille va évoluer au cours du temps, en fonction de la configuration de son voisinage. Plus précisément, chaque automate est défini par 3 paramètres : states = le nombre d'états possibles pour chaque cellule, peers = la liste des cellules voisines à prendre en compte pour contrôler l'évolution d'une cellule, et rules = un ensemble de règles de transition pour définir chacune des configurations permettant à une cellule de passer d'un état X vers un état Y.



A titre d'exemple, l'image de gauche de la figure ci-dessus montre une animation du modèle WireWorld qui a été développé pour simuler le comportement des circuits électriques. Dans le cadre de ce projet, ce modèle sera défini par un dictionnaire Python (cf. code ci-dessous) contenant les valeurs associées aux 3 paramètres states, peers et rules. Pour ce modèle, chaque cellule peut prendre un des 4 états possibles (A, B, C ou D), symbolisés par des couleurs (A = noir = vide, B = jaune = conducteur électrique, C = bleu = début du signal, D = rouge = fin du signal). Les cellules voisines à prendre en compte pour l'évolution d'une cellule sont identifiées par un ensemble de 8 vecteurs de translation, permettant de trouver les coordonnées des 8 cases voisines. Et enfin, les différentes règles de transition sont spécifiées par une liste de couples, où chaque couple est composés d'une chaîne de 2 caractères (représentant respectivement l'état initial et l'état final de la transition considérée) et d'un dictionnaire (décrivant la configuration nécessaire du voisinage pour activer cette transition). Par exemple la règle 'AA',{} signifie qu'une cellule dans l'état A (case noire) va rester dans l'état A, quelque soit la configuration de son voisinage (on peut effectivement constater sur l'animation, que les cases noires ne changent jamais de couleur). De même, la règle 'BC',{'C':{1,2}} signifie qu'une cellule va passer de l'état B (case jaune) à l'état C (case bleue) dès qu'il y a 1 ou 2 cellules, parmi ses 8 voisins, qui sont dans l'état C. Par convention, les règles de transition sont toujours ordonnées par rapport à l'état initial, et s'il y a plusieurs règles qui s'appliquent à un même état initial, celles-ci sont systématiquement classées de la plus spécifique à la plus générique. Ainsi, pour l'automate WireWorld, la règle 'BB':{} ne s'appliquera que si la règle 'BC':{'C':{1,2}} a échoué.

wireworld = {
  'states': 'ABCD',
  'peers': [(-1,0),(1,0),(0,-1),(0,1),(-1,-1),(-1,1),(1,-1),(1,1)],
  'rules': ['AA',{}, 'BC',{'C':{1,2}}, 'BB',{}, 'CD',{}, 'DB',{}]
}
L'image de droite de la figure montre une animation résultant d'un autre modèle classique d'automate cellulaire, appelé Greenberg-Hastings, dont l'intérêt principal est de permettre de simuler la propagation de certaines réactions chimiques dans les fluides.

Pour simplifier le développement du programme, on fournit une archive autocell.zip qui contient d'une part un fichier automata.py regroupant les paramètres de définition de 9 modèles classiques d'automates cellulaires, et d'autre part, le fichier automata.ini qui contient, pour chacun de ces 9 modèles, quelques exemples de configurations initiales permettant d'obtenir des évolutions intéressantes lors de la simulation. L'objectif du projet sera donc de lire ces fichiers de données, de permettre à l'utilisateur de choisir un modèle d'automate et une configuration initiale, puis de visualiser graphiquement l'évolution de la grille au cours du temps, en appliquant les règles de transition adéquates pour chacune des cellules en fonction de son voisinage. On pourra évidemment rajouter d'autres modèles d'automates ou des configurations initiales personnalisées ; la seule contrainte étant de rester dans le même formalisme de description. De même, toutes les améliorations de l'interface permettant d'apporter des fonctionnalités supplémentaires seront les bienvenues (on pourra librement s'inspirer de ce qui est proposé sur le site conwaylife.com déjà cité plus haut). Dernière remarque : pour gagner en vitesse d'affichage (notamment lorsque le nombre de cellules est important) il est fortement conseillé d'afficher la grille via une widget Canvas au lieu d'un ensemble de widgets Brick.

Exemples à relire avant de commencer le projet :
  1. Exemple C7A_canvas.py (pour l'utilisation générale de la widget Canvas)
  2. Exercice C8A_maze.py (pour l'affichage d'une grille dans un Canvas)
  3. Exemple B5A_inifile.py (pour la lecture des fichiers INI)
Philippe Blasi