PYTHON : PROJETS 2023

L'objectif des projets proposés sur cette page, est de combiner le paradigme de programmation objet avec la réalisation d'un programme mettant en oeuvre la séparation noyau/interface. Pour chacun des projets, il faudra donc mettre en place une organisation du code composée de deux ensembles de classes :

Projet 1 : "Penté" à deux joueurs

Ecrire un programme Pente qui implémente une version à deux joueurs du jeu du même nom. Le "Penté" se joue sur une grille carrée de taille variable, et constitue une variante plus complexe du très classique "Morpion". Chaque joueur pose un pion, à tour de rôle, et tente de former l'une des deux combinaisons gagnantes : Le vainqueur de la partie est celui qui obtient le nombre de points convenu au départ entre les joueurs (habituellement, une partie se joue en 5, 10 ou 15 points). Afin de limiter au maximum, l'avantage du joueur qui démarre la partie, les règles modernes de "Penté" incluent une restriction pour la pose des pions : aucun joueur ne peut poser un pion sur l'une des 8 cases entourant le pion qu'il a posé au tour précédent, ce qui interdit certaines combinaisons permettant de gagner à coup sûr. Le jeu peut être testé sur une version en ligne mais malheureusement celle-ci n'implémente pas la restriction des placements de pions.

La figure ci-dessus illustre le type d'interface graphique qui est demandée :
  1. Au lancement du programme, une fenêtre de configuration doit s'afficher (cf. image de gauche) permettant de saisir le nom des deux joueurs, ainsi que les deux paramètres numériques : la taille du plateau (entre 8x8 et 16x16) ainsi que le nombre de points à réaliser pour gagner la partie (entre 5 et 15)
  2. Ensuite, lorsqu'on clique sur le bouton "START", cette fenêtre de configuration est remplacée par une nouvelle fenêtre qui affiche la grille de jeu (cf. image de droite). Dans la zone du haut sont rappelés les noms et les scores de chaque joueur, et au centre, la lettre A ou B indique le joueur actif. La zone du bas présente l'état courant du plateau de jeu, avec les cases vides (en noir), les pions du joueur A (en bleu), les pions du joueur B (en vert). A chaque coup, le programme colorie en gris les cases vides voisines du pion posé par le joueur actif lors de son dernier tour. Selon la règle de restriction de pose, ces cases sont donc invalidées pour ce tour de jeu. Pour jouer son coup, chaque joueur clique simplement sur la case choisie.
  3. Le programme doit évidemment détecter les configurations d'alignement et de capture des pions et actualiser les scores en conséquence (concrètement, à chaque coup, il suffit d'explorer le voisinage de la case joué pour vérifier si ce coup engendre un alignement ou une capture). La victoire de l'un ou l'autre des joueurs donnera lieu à un affichage spécifique (animation des pions sur le plateau ou fenêtre pop-up)
La partie "noyau" de l'implémentation demandée doit se baser sur une classe qui permet la gestion d'une grille de jeu carrée de dimension quelconque. A l'intérieur de ce noyau, la grille va être représentée par une matrice 2D dont les éléments sont des valeurs entières caractérisant de manière symbolique, le contenu de chaque case de la grille (par exemple, 0 représentera une case vide, 1 une case avec un pion bleu, etc). La classe correspondante devra notamment gérer l'ajout et la suppression des pions durant les tours de jeu, la détection des configuration d'alignement et de capture, ainsi que le calcul du score (il faut noter que plusieurs alignements et/ou capture peuvent être obtenus durant le même coup).

La partie "interface" de l'implémentation devra mettre en oeuvre tout ce qui concerne la sélection de la taille de la grille de jeu, l'affichage du plateau, des pions et des scores, le contrôle des actions effectuées à la souris par les joueurs. Pour simplifier la mise en oeuvre, on fournit une archive ZIP contenant la grille des images correspondant aux 4 états possible d'une case (case vide valide, pion bleu, pion vert, case vide invalide) ainsi qu'un fichier squelette pour le code à réaliser.

Exemples à relire avant de commencer le projet :
  1. Exemple D6_peg.py (pour la séparation noyau/interface d'un programme)
  2. Exemple E5C_win.py (pour la gestion de l'alternance entre les 2 fenêtres)
  3. Exercice E6A_slide.py (pour la mise en oeuvre globale de l'interface)

Projet 2 : Drop

Ecrire un programme Drop qui implémente le jeu du même nom disponible sur différentes plateformes de jeu en ligne, telles que CoolMathGames. Le gameplay de Drop se présente comme un mélange de deux grands classiques du jeu vidéo, Columns d'un côté, et 2048 de l'autre. En effet, le but du jeu est (comme dans Columns) d'arriver à former des assemblages d'au moins 3 blocs adjacents de la même couleur, et (comme dans 2048) chaque fois qu'un tel assemblage est obtenu, il va être effacé et remplacé par un bloc de plus haut niveau, caractérisé par une nouvelle couleur. Le score du joueur est calculé en fonction de la taille des assemblages réalisés, multipliés par le niveau des blocs utilisés.

La figure ci-dessus illustre le type d'interface graphique qui est demandée, et qui est relativement proche de la version disponible en ligne :
  1. Au lancement du programme, une fenêtre de configuration doit s'afficher (cf. image de gauche) permettant de saisir le nombre de lignes (entre 6 et 12) et le nombre de colonnes (entre 6 et 12, également) de la grille de jeu, ainsi que le nombre de couleurs (entre 1 et 12) qui peuvent apparaître dès le départ pour les blocs à assembler. Au cours de la partie, le nombre de couleurs pour les blocs va augmenter au fur et à mesure que le joueur obtient de nouvelles couleurs par assemblage des blocs.
  2. Ensuite, lorsqu'on clique sur le bouton "START", cette fenêtre de configuration est remplacée par une nouvelle fenêtre qui affiche la grille de jeu (cf. image de droite). La partie haute montre le bloc bicolore que le joueur peut déplacer avant de le faire tomber dans la partie centrale, où se produisent les assemblages de couleurs. La partie basse affiche, à gauche, 12 cases correspondants aux 12 couleurs identifiant les différents niveaux des blocs, et à droite, la valeur du score pour la partie en cours.
  3. Le jeu se pilote entièrement au clavier : les flèches droites et gauche permettent de déplacer le bloc tant qu'il est sur la ligne du haut, la flèche vers le haut permet de permuter les 2 couleurs du bloc, et la flèche vers le bas actionne la chute du bloc qui va s'arrêter en contact des blocs déjà présents dans la grille.
Pour simplifier la mise en oeuvre, on fournit une archive ZIP qui contient un squelette pour le code à réaliser. La partie "noyau" de l'implémentation demandée pourra s'inspirer de la classe GravityGrid (Exercice D9) qui permet de gérer une grille de taille variable où les éléments stockés dans les cases sont soumis à la gravité (le code complet de cette classe se trouve également dans l'archive ZIP. La partie "interface" de l'implémentation devra mettre en oeuvre tout ce qui concerne l'affichage de la grille de jeu et du score courant, le contrôle des actions effectuées par le joueur, et la création de l'animation en fin de partie.

De manière optionnelle, on pourra également rajouter un mode de jeu "dynamique" dans lequel les pièces descendent automatiquement dans la grille lorsque le temps s'écoule, pour forcer le joueur à prendre ses décisions plus rapidement.

Exemples à relire avant de commencer le projet :
  1. Exemple D6_peg.py (pour la séparation noyau/interface d'un programme)
  2. Exemple E5C_win.py (pour la gestion de l'alternance entre les 2 fenêtres)
  3. Exercices D9A_gravitygrid (pour la gestion de la grille et de la gravité)
  4. Exercice E6B_slide.py (pour la mise en oeuvre globale de l'interface)

Projet 3 : ComboColor

Ecrire un programme ComboColor qui implémente une variante simplifiée du jeu de société Combo Color édité par Asmodée. C'est un jeu de conquête territoriale pour 2 à 4 joueurs, qui se joue en coloriant au feutre les cases d'un plateau de jeu, afin de réaliser les combinaisons permettant de marquer le plus de points. La description du jeu se trouve sur le site du "Labo des Jeux" et l'explication complète des règles en vidéo, se trouve sur la chaîne"Explique-moi ça".


Dans la variante simplifiée proposée dans le cadre du projet, le jeu se limite à 2 joueurs possédant chacun 2 couleurs (rouge et bleu pour le joueur A, vert et jaune pour le joueur B). De plus, le plateau de jeu est une simple grille composée de 24 zones de 5 cases chacune (cf. image ci-dessus). Chaque zone est taggée avec l'un des trois types de labels permettant d'identifier la valeur de la zone pour le décompte final des points : un label bleu correspond à des points additifs, un label rouge à des points soustractifs et un label vert à des points multiplicatifs. Les scores se calculent par couleur: on effectue le total des points bleus auxquels on retranche le total des points rouges, et on multiplie le résultat obtenu par le total des points verts. Le score global de chaque joueur est défini à tout moment comme le produit des scores correspondants à ses deux couleurs. C'est évidemment le programme qui se charge à chaque tour de jeu, du calcul et de l'affichage de l'évolution des scores. Pour le coloriage des différentes zones lors des tours de jeu, le plus simple est d'utiliser la bibliothèque Pillow qui fournit de nombreux algorithmes de traitement d'images, et en particulier, une fonction floodfill qui permet de remplir une zone homogène d'une image avec une couleur spécifiée.

On fournit une archive ZIP contenant une série de fichiers utiles pour la réalisation du projet. Il y a notamment les images PNG de 6 plateaux de jeu différents (chacun basé sur une grille de taille 11x11), ainsi qu'un encodage de ces 6 plateaux sous la forme d'un fichier texte semi-structuré, permettant d'identifier la nature des labels de score pour chacune des cases. L'archive contient également un fichier "combocolor.txt" qui donne quelques explications complémentaires sur certains éléments à mettre en oeuvre dans le code à fournir.

Comme pour les projet précédents, il faudra créer une (ou plusieurs) classe(s) pour le noyau du jeu, permettant de modéliser le jeu de manière abstraite, puis une (ou plusieurs) classe(s) pour l'interface graphique qui mettra en oeuvre la visualisation du plateau de jeu et la gestion des actions des deux joueurs. Mais à la différence des projets précédents, on ne fournit pas de fichier squelette comme point de départ pour le code à réaliser.

Exemples à relire avant de commencer le projet :
  1. Exemple E5C_win.py (pour la gestion de l'alternance entre les 2 fenêtres)
  2. Exemple D6_peg.py (pour la séparation noyau/interface d'un programme)
  3. Exercice E9A_pixelart.py (pour la lecture et l'analyse du fichier texte)
  4. Exemple E8C_pillow.py (pour le coloriage d'une zone de forme quelconque)

Projet 4 : OSCAR

Depuis leur développement il y a près de 30 ans, les systèmes multi-agents (SMA) ont été utilisés avec succès dans divers domaines. En éthologie, par exemple, les SMA servent comme outil de simulation pour étudier le comportement des insectes sociaux (fourmis, abeilles, etc). Dans ce contexte, les SMA consistent à définir un ensemble d'automates communicants qu'on laisse évoluer au cours du temps, afin de voir si l'on peut reproduire des comportements sociaux observés dans la nature. Le but du projet est de réaliser un petit simulateur appelé oscar (Outil de Simulation Comportemental par Attraction-Répulsion) consistant à animer des agents sur une grille, en fonction d'un modèle de comportement très simple basé sur un concept d'attraction-répulsion.

Voici les principales caractéristiques du modèle utilisé : La description du terrain ainsi que des caractéristiques des agents utilisés pour une simulation particulière s'effectue par le biais d'un fichier texte, qui sera interprété par le programme avant de démarrer la simulation. Ce fichier de structure très simple se compose d'une série de blocs (c'est-à-dire des groupes de lignes séparées par au moins une ligne vide), chacune définissant une des 5 commandes possibles: world, mineral, vegetal, animal et agent. De plus, lorsqu'un caractère # apparait sur une ligne du fichier, les caractères à sa droite jusqu'à la fin de la ligne, sont considérés comme du commentaire.

Mise à part la commande world, toutes les commandes peuvent apparaitre plusieurs fois, pour définir différents états ou différents agents. Dans la syntaxe ci-dessous, les termes en gras correspondent à des mots-clés et doivent donc apparaitre littéralement, alors que les autres termes correspondent à des paramètres et doivent être remplacés par une valeur numérique (pour les termes en italiques) ou alphanumérique (pour les termes en romanes). Le symbole <|> signifie que l'on peut mettre soit le signe inférieur soit le signe supérieur, afin de définir le sens de comparaison d'un paramètre par rapport à une valeur de seuil.

world NumberRows NumberCols VoidIcon_or_VoidColor

mineral StatusName StatusIcon_or_StatusColor
var VariableName InitValue TimeStepValue
status VariableName <|> ThresholdValue NewStatusName
field FieldName DistanceStepValue
sensor SensorName FieldName SensitivityValue

vegetal StatusName StatusIcon_or_StatusColor
var VariableName InitValue TimeStepValue
status VariableName <|> ThresholdValue NewStatusName
birth VariableName <|> ThresholdValue NewbornStatusName
field FieldName DistanceStepValue
sensor SensorName FieldName SensitivityValue

animal StatusName StatusIcon_or_StatusColor
var VariableName InitValue TimeStepValue
status VariableName <|> ThresholdValue NewStatusName
birth VariableName <|> ThresholdValue NewAgentStatusName
trace VariableName <|> ThresholdValue NewTraceStatusName
field FieldName DistanceStepValue
sensor SensorName FieldName SensitivityValue

agent StatusName (row,col) (row,col) ...
agent (StatusNameA,StatusNameB,...) (rowA:rowB:step,colA:colB:step) ...
Pour mieux comprendre le rôle de ce fichier de configuration, voici quelques exemples simples qui correspondent à des simulations classiques:
Les 3 premiers exemples n'utilisent que l'ordre mineral des agents, ce qui permet de valider votre moteur sans avoir besoin d'implémenter l'ensemble des fonctionnalités. Les autres exemples utilisent également les ordres vegetal et animal. Ces six fichiers de configuration sont regroupés dans une une archive ZIP qui contient également un fichier "oscar.txt" donnant quelques explications complémentaires sur certains éléments à mettre en oeuvre dans le code à fournir.

...
Christophe Schlick