Code - Compétence 7
import os
import copy
colors = { # Couleurs pour l'affichage
"red": "\033[031m",
"green": "\033[032m",
"black": "\033[30m",
"bgwhite": "\033[107m",
"bgblack": "\033[100m",
"reset": "\033[0m",
"bold": "\033[1m",
"blue": "\033[34m",
"white": "\033[37m",
"black_back": "\033[40m",
"red_back": "\033[41m",
"blue_back": "\033[42m",
"gras": "\033[1m",
"inverse": "\033[7m"
}
class Puissance4:
def __init__(self):
"""
Initialise la grille de jeu et initialise les variables de jeu
PréCondition : Aucune
PostCondition : Initialise la grille de jeu et les variables de jeu
"""
self.grille = [
[], [], [], [], [], [], [] # Initialise une grille vide de 7 sous-tableaux
]
self.isEnded = False # Le jeu n'est pas terminé
self.playingPlayer = 1 # Le joueur 1 commence
def clear(self):
"""
En fonctions de l'OS, on change la commande pour vider la console
PréCondition : Aucune
PostCondition : Vide la console
"""
os.system(
'cls' if os.name == 'nt' else 'clear') # En fonction de l'OS, on vide la console avec "clear" ou "cls" (nt = Windows)
def ajouter_jeton(self, joueur, colonne):
"""
Vérifie si la colonne est valide et ajoute le jeton dans la colonne
Paramètres : joueur (Qui est 1 ou 2) et la colonne dans laquelle doit être ajoutée le jeton
PostCondition : Modifie la grille et retourne un bouléan en fonction du succès de l'ajout
"""
if (not self.verif_ajout(colonne)):
return False
self.grille[colonne].append(joueur)
return True
def reset_partie(self):
"""
Réinitialise la grille de jeu en remettant toutes les colonnes à vide
PréCondition : Aucune
PostCondition : Réinitialise la partie
"""
self.grille = [
[], [], [], [], [], [], []
]
def verif_ajout(self, colonne):
"""
Vérifie si la colonne est dans la grille vérifie si la colonne n'est pas pleine
Précondition : colonne doit être un entier
PostCondition : Retourne un booléen en fonction de la validité de la colonne
"""
if (colonne < 0 or colonne > 6): # Colonne pas dans la grille (compris entre 0 et 6)
print("not in range")
return False
if (len(self.grille[colonne]) > 6): # Colonne plein (nb de jetons >6)
print("full")
return False
return True
def afficher_grille(self):
"""
Retourne la grille de jeu à 90° gauche afin de ne pas a avoir à gérer les lignes et affiche la grille de jeu
PréCondition : Aucune
PostCondition : Affiche la grille de jeu
"""
tableauRenverse = [[], [], [], [], [], [], []] # On créer un tablau pour l'instant vide que l'on va reverser
for ligne in range(7):
for colonne in range(len(self.grille[ligne])): # On boucle les lignes et les là où en est les colonnes
if self.grille[ligne][colonne] == 1: # Si la case est marquée par le joueur 1
tableauRenverse[ligne].append(colors['blue'] + "o" + colors['white']) # On ajouter un O bleu
elif self.grille[ligne][colonne] == 2: # Sinon, c'est l'autre joueur
tableauRenverse[ligne].append(
colors["red"] + "x" + colors["white"]) # Un X rouge si c'est l'autre joueur
for p in range(5 - len(self.grille[ligne])):
tableauRenverse[ligne].append(
" ") # Et on complète avec des espaces là où il y a du vide pour simplifier la suite.
"""
Lourde partie de formattage qui permet d'avoir le rendu du plateau, ici il est vraiment très manuel et réalisé
a l'aide d'ASCII Art. https://www.asciiart.eu/
"""
print(colors['white'] + ' 1 2 3 4 5 6 7 ')
print(' ')
print(' ║', tableauRenverse[0][4], '║', tableauRenverse[1][4], '║', tableauRenverse[2][4], '║',
tableauRenverse[3][4], '║', tableauRenverse[4][4], '║', tableauRenverse[5][4], '║', tableauRenverse[6][4],
'║ ')
print(' ║', tableauRenverse[0][3], '║', tableauRenverse[1][3], '║', tableauRenverse[2][3], '║',
tableauRenverse[3][3], '║', tableauRenverse[4][3], '║', tableauRenverse[5][3], '║', tableauRenverse[6][3],
'║ ')
print(' ║', tableauRenverse[0][2], '║', tableauRenverse[1][2], '║', tableauRenverse[2][2], '║',
tableauRenverse[3][2], '║', tableauRenverse[4][2], '║', tableauRenverse[5][2], '║', tableauRenverse[6][2],
'║ ')
print(' ║', tableauRenverse[0][1], '║', tableauRenverse[1][1], '║', tableauRenverse[2][1], '║',
tableauRenverse[3][1], '║', tableauRenverse[4][1], '║', tableauRenverse[5][1], '║', tableauRenverse[6][1],
'║ ')
print(' ║', tableauRenverse[0][0], '║', tableauRenverse[1][0], '║', tableauRenverse[2][0], '║',
tableauRenverse[3][0], '║', tableauRenverse[4][0], '║', tableauRenverse[5][0], '║', tableauRenverse[6][0],
'║ ')
print(' ╚═══╩═══╩═══╩═══╩═══╩═══╩═══╝ ')
print(' ')
def victoire_anim(self, joueur):
"""
Affiche l'animation de victoire, demande à l'utilisateur d'appuyer sur entrée, réinitialise la partie et redémarre le jeu.
PréCondition : Aucune
PostCondition : Affiche l'animation de victoire
"""
self.clear() # On vide la console
if joueur == 1: # On fonction du joueur on prévoit la couleur liée et le texte à afficher
joueur = colors['blue'] + "JOUEUR 1" + colors["green"]
else:
joueur = colors['red'] + "JOUEUR 2" + colors["green"]
# Même concept que pour l'affichage du plateau, tout est fait en ASCII Art, on y ajoute le texte qu'on a créé plus tôt
print(colors['gras'] + colors['green'])
print(' _ _ ')
print(' \\\\ // ¤ ╔═══╗ ══╦══ ╔═══╗ ¤ ╔═══╗ ╔═══ ')
print(' \\\\ // ║ ║ ║ ║ ║ ║ ║ ║ ╠══ ')
print(' \\\// ║ ║ ║ ║ ║ ║ ╠══╦╝ ║ ')
print(' \/ ║ ╚═══╝ ║ ╚═══╝ ║ ║ ╚╗ ╚═══ ')
print(' ')
print(' ╔══════════════════╗ ')
print(' ────════╣ ' + joueur + ' ╠════──── ')
print(' ╚══════════════════╝ ')
print("")
print(' PRESS << enter >> ')
input() # On pause l'entrièreté du process pour attendre une réaction du joueur
self.clear() # On vide le terminal et on redémarre la partie procéduralement
self.reset_partie()
self.demarrer_jeu()
def verif_gagnant(self):
"""
Crée une copie de la grille, ajoute des 0 pour compléter la grille, et vérifie si il y a une victoire en ligne, colonne ou diagonale
PréCondition : Aucune
PostCondition : Retourne un booléen en fonction de la victoire
"""
l = copy.deepcopy(
self.grille) # Création d'une deepcopy du tableau afin d'éviter la réécriture sur la référence mémoire
for k in range(7): # On remplis lescoloones vides par des 0
while len(l[k]) < 5:
l[k].append(0)
for y in range(5): # On parcours toutes les cases afin de vérifier toutes les conditions de victoire
for x in range(7):
if l[x][y] != 0: # Si la case n'est pas un 0
jeton = l[x][y] # La valeur est définie aux coordonées x et y dans la grille
if x < 4: # Afin d'éciter les OutOfBoundsExeption, on recherche uniquement quand x > 4
if jeton == l[x + 1][y] and jeton == l[x + 2][y] and jeton == l[x + 3][
y]: # Vérifie si il y a une victoire en ligne
return True
if y < 2: # De même pour les y, on vérifie par la hauteur
if jeton == l[x][y + 1] and jeton == l[x][y + 2] and jeton == l[x][
y + 3]: # Vérifie si il y a une victoire en colonne
return True
if y < 2 and x < 4: # Et de même pour les diagonales, on vérifie si les coordonnées sont dans le terrain de jeu
if jeton == l[x + 1][y + 1] and jeton == l[x + 2][y + 2] and jeton == l[x + 3][
y + 3]: # Vérifie si il y a une victoire en diagonale
return True
if y < 2 and x > 2: # On revérifie pour les diagonales dans l'autre sens.
if jeton == l[x - 1][y - 1] and jeton == l[x - 2][y - 2] and jeton == l[x - 3][y - 3]:
return True
def demander_colonne(self):
"""
Vérifier qu'il n'y ai pas une victoire, demande la colonne à l'utilisateur, si la colonne est valide, ajoute le jeton dans la colonne sinon, affiche un message d'erreur et redemande la colonne.
PréCondition : Aucune
PostCondition : Demande la colonne à l'utilisateur et ajoute le jeton dans la colonne*
"""
global colonne
if (self.verif_gagnant()): # Si il y a un gagnant
winner = 1 if self.playingPlayer == 2 else 2 # On le définit au joueur qui n'est pas en train de joueur
self.victoire_anim(winner) # Et ici on affiche l'animation de victoire
return
if (self.playingPlayer == 1): # Dans le flow d'execution classique on demande au joueur 1 ou 2 de jouer.
print(colors["bgwhite"] + colors["red"] + "> Joueur 1")
else:
print(colors["bgwhite"] + colors["green"] + "> Joueur 2")
print(colors["reset"])
try:
colonneDemandee = input("Colonne : ") # Ensuite, on demande la colonnne qu'il souhaite affecter
if (colonneDemandee == "exit"): # Commande pour stopper le programme.
self.isEnded = True
return
elif (colonneDemandee == "80085"):
print("Holà qué tal ?")
x = True
while x:
input()
x = False
colonne = int(colonneDemandee) - 1
except: # Si il y a une erreur (StringToIntegerExeption) on affiche un message dans la console et on redemande au joueur de jouer
self.clear()
print(colors["red"] + "INVALIDE, rééssayez" + colors["black"])
self.afficher_grille()
self.demander_colonne()
try:
ajout = self.ajouter_jeton(self.playingPlayer,
colonne) # Et ici on essaye d'ajouter la colonne mais en vérifiant qu'elle rentre bien dans le plateau
if (ajout):
self.playingPlayer = 2 if self.playingPlayer == 1 else 1 # Sinon on change de joueur à jouer
else: # Si ça n'a pas ajouter on affiche une erreur
self.clear()
print(colors["red"] + "INVALIDE, rééssayez" + colors["black"])
self.afficher_grille()
self.demander_colonne()
except: # En cas d'Exeption, on redemande
self.clear()
print(colors["red"] + "INVALIDE, rééssayez" + colors["black"])
self.afficher_grille()
self.demander_colonne()
def demarrer_jeu(self):
"""
Permet de lancer le jeu.
Configure le jeu pour les éléments de base, affiche le logo du jeue execute la boucle de jeu principale
PréCondition : Aucune
PostCondition : Démarre le jeu | Ne retourne rien
"""
self.clear() # On vide le terminal
print(colors['red']) # En rouge, on affiche le logo en Ascii Art.
print(' ')
print(' ──╦═══════════════════════════════╦── ')
print(' ──╦─╣ ╔═══╗ ╠─╦── ')
print(' ───╦─╣ ║ ║ ║ ║ ╠─╦─── ')
print(' ──────╣ ╠═══╝ ╚═══╬═ ╠───── ')
print(' ───╩─╣ ║ ║ ╠─╩─── ')
print(' ───╩─╣ ║ u i s s a n c e ║ ╠─╩── ')
print(' ───╩═══════════════════════════════╩── ')
print(' ')
print(' PRESS << enter >> ')
input()
self.clear() # Une fois que l'utilisateur a cliqué, on lance la boucle while
while (not self.isEnded):
self.afficher_grille() # Tant que lejeu n'est pas fini, on affiche la grille,
self.demander_colonne() # On demande la colonne a affecter
self.clear() # On vide le terminal
puissance4Game = Puissance4()
puissance4Game.demarrer_jeu()
# Assertion 1 : Vérifie si la fonction verif_ajout retourne True si la colonne est valide
assert puissance4Game.verif_ajout(0) == True
# Assertion 2 : Vérifie si la fonction verif_ajout retourne False si la colonne n'est pas valide
assert puissance4Game.verif_ajout(7) == False
# Assertion 3 : Vérifie si la fonction verif_ajout retourne False si la colonne est pleine
puissance4Game.grille[0] = [1, 1, 1, 1, 1, 1]
assert puissance4Game.verif_ajout(0) == False
# Assertion 4 : Vérifie si la fonction ajouter_jeton ajoute bien un jeton
puissance4Game.reset_partie()
puissance4Game.ajouter_jeton(1, 0)
assert puissance4Game.grille[0] == [1]
# Assertion 5 : Vérifie si la fonction ajouter_jeton retourne False si la colonne est pleine
puissance4Game.grille[0] = [1, 1, 1, 1, 1, 1]
Last modified: 30 septembre 2024