Pour ce projet, vous allez concevoir un jeu de Puissance 4 et une IA pour y jouer.

Au Puissance 4, deux joueurs s'affrontent autour d'un plateau de 7 colonnes et 6 lignes. Chacun leur tour, les joueurs choissent une colonne à jouer et y déposent un jeton de leur couleur (rouge pour le joueur 1, jaune pour le joueur 2) à la position la plus basse possible dans la colonne. Le premier joueur qui arrive à aligner 4 jetons en ligne, en colonne ou en diagonale est déclaré gagnant.
Pour ce projet, un ensemble de fichiers vous est fourni. Cliquez sur le lien ci-dessous pour les télécharger.
Télécharger les fichiers du projet.
Une fois l'archive téléchargée, ouvrez-la et déplacez les fichiers sur votre espace de stockage persistant dans le dossier projets/connect4.
Les fichiers sont les suivants :
main.py : Le script à exécuter pour lancer le jeu de Puissance 4.solver.py : Le fichier qui contient les fonctions pour jouer de manière automatique au Puissance 4.state.py : Le fichier qui contient les fonctions pour manipuler l'état d'un jeu de Puissance 4.ui.py : Le fichier qui contient le code de l'interface graphique proposée pour jouer.Ces quatre fichiers sont à mettre dans votre dossier projets/connect4. Pour cette première étape, nous allons principalement modifier le fichier state.py.
Le fichier solver.py sera le sujet des étapes suivantes.
Pour la première étape du projet, vous allez concevoir la classe Board qui permettra de représenter l'état d'un plateau de jeu de Puissance 4.
Un squelette de la classe vous est déjà fourni, dans le fichier state.py. Le contenu du fichier est le suivant :
class Board(object):
def __init__(self, width=7, height=6, connect=4):
pass
def get_width(self):
pass
def get_height(self):
pass
def get_connect(self):
pass
def get_next_player(self):
pass
def get_token(self, x, y):
pass
def free_columns(self):
pass
def play(self, column):
pass
def unplay(self, column):
passLes différentes méthodes sont décrites ci-dessous. Vous êtes libre de la façon dont vous implémentez ces méthodes, pour autant que vous suiviez ce qui est décrit.
__init__Le constructeur __init__ a trois paramètres en plus de self :
width, la largeur du tableau,height, la hauteur du tableau,connect, le nombre de jeton à aligner pour gagner.Ces paramètres ont tous une valeur par défaut qui correspond aux valeurs traditionnellement admises au Puissance 4.
get_widthLa méthode get_width doit retourner la largeur du plateau de jeu.
get_heightLa méthode get_height doit retourner la hauteur du plateau de jeu.
get_connectLa méthode get_connect doit retourner le nombre de jetons à aligner pour gagner.
get_next_playerLa méthode get_next_player doit indiquer à qui c'est de tour de jouer un pion. Pour le joueur 1, la valeur 1 est attendue, alors que pour le joueur 2, on attend -1.
Vous pouvez partir du principe que la méthode ne sera appelée que lorsque le jeu n'est pas terminé.
get_tokenRetourne le jeton situé à une position précise du tableau.
On attend la valeur 1 pour un jeton du premier joueur, la valeur -1 pour un jeton du second joueur, et la valeur 0 pour une case vide.
L'argument x indique la colonne (depuis la gauche) et l'argument y la ligne (en partant du bas).

Afin de simplifier l'implémentation de votre fonction play plus bas, et en particulier la vérification de l'existence d'une séquence de jetons gagnante, faites en sortes de retourner None (ou 0) lorsque la position donnée est hors du plateau.
free_columnsLa méthode free_columns doit retourner une listes des colonnes qui peuvent être jouées, c'est-à-dire des colonnes qui contiennent un emplacement libre. Chaque colonne sera identifiée par son numéro de colonne (de 0 à self.get_width() - 1).
playLa méthode play doit permettre de jouer le pion d'un joueur dans la colonne indiquée et de passer le tour au joueur suivant.
Si par ce coup le joueur gagne, alors la méthode devra retourner True. La méthode devra retourner False autrement. Pour cela, il faudra vérifier à ce moment s'il existe une ligne, une colonne ou un diagonale de jetons du joueur de longueur au moins self.get_connect().
Pour vérifier si un groupe de longueur self.get_connect() jetons de la couleur du joueur existe après l'insertion d'un jeton, il suffit de contrôler les groupes qui contiennent le dernier jeton inséré.
Il y a donc self.get_connect() groupes horizontaux à vérifier, un unique groupe vertical au maximum à vérifier et self.get_connect() groupes pour chacune des deux diagonales à vérifier.
Dans chaque groupe, il y a self.get_connect() positions à vérifier.
Il faudra donc utiliser une boucle pour parcourir tous les groupes et, à l'intérieur de cette boucle, utiliser une autre boucle pour parcourir toutes les positions contenues dans le groupe. Il peut être intéressant de séparer le traitement des groupes horizontaux, verticaux, et des deux diagonales.
Vous pouvez utiliser self.get_token afin d'accéder à un token du plateau. Ceci peut être utile afin de ne pas à avoir à ce soucier de savoir si la position est bien à l'intérieur du plateau de jeu.
unplayLa méthode unplay doit retirer le jeton le plus haut de la colonne indiquée et passer le tour à l'autre joueur.
On partira du principe que la colonne dans laquelle le jeton doit être enlevée est la dernière colonne dans laquelle un jeton a été joué.
Une fois votre classe définie, vous pourrez tester le bon fonctionnement de votre code en lançant une partie de Puissance 4 entre deux joueurs humains.
Pour cela, il vous suffira simplement d'exécuter le script main.py.