#Projet final de NSI #Date: 06/05/2025 #version:1 #thême:Puissance 4 #Travail réalisé à 2 #Yann: #-grille #-pions #Hugo #-interactivité #-bouton #-comande de restaure, sauvegarder, quitter, recommencer #Cette version manque: #-la posibilié de gagner une partie #-affronter une IA #-les scores #Cette veriosn permet de: #-jouer au jeux #-quitter #-sauvegarder #-recommencer #-restaurer from turtle import * # ############################################################################ # D E C L A R A T I O N D E S V A R I A B L E S G L O B A L E S # ############################################################################ # Structure de donnée mémorisant la grille : une liste à 2 dimensions (6 lignes et 7 colonnes) contenant : # - un 0 si la case est vide # - un 1 si un pion ROUGE est dans la case # - un 2 si un pion BLEU est dans la case grille=[7*[0], 7*[0], 7*[0], 7*[0], 7*[0], 7*[0]] # liste_colonne mémorise le nombre de pions dans chacune des colonnes liste_colonne=7*[0] # joueur_courant indique le prochain joueur qui doit jouer : 1 pour ROUGE et 2 pour BLEU joueur_courant=1 # ############################################################################ # D E C L A R A T I O N D E S F O N C T I O N S # ############################################################################ # ############################################################################ # La fonction afficher_grille() affiche la grille sur la sortie standard def afficher_grille(): for i in range(6): print(grille[i]) # affiche le repère des colonnes sous la grille : print('\n 0 1 2 3 4 5 6') # ############################################################################ # La fonction grille_pleine() teste si la grille est pleine (aucun 0 dans la liste grille) def grille_pleine(): b_plein=True for i in range(6): for j in range(7): if grille[i][j]==0: # retourne False si au moins une case est vide b_plein=False return b_plein # ############################################################################ # La fonction jouer(x,y) est appelé si on clique gauche sur le point (x,y) def jouer(x,y): # utilise la variable globale joueur_courant : global joueur_courant # teste si la grille est pleine : if grille_pleine(): print("Fin de la partie : la grille est pleine. Appuyez sur Echap pour recommencer une nouvelle partie.") else: # analyse la zone cliquée pour déterminer la colonne : if x_base=4: trouve=1 print("Bravo le joueur rouge à gagné") return trouve elif grille[i][j]==2: rouge=0 bleu+=1 if bleu>=4: trouve=2 print("Bravo le joueur bleu à gagné") return trouve else: rouge=0 bleu=0 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # teste 4 pions alignés verticalement en alanysant chacune des 7 colonnes : for j in range(7): rouge=0 bleu=0 for i in range(6): if grille[i][j]==1: rouge+=1 bleu=0 if rouge>=4: trouve=1 print("Bravo le joueur rouge à gagné") return trouve elif grille[i][j]==2: rouge=0 bleu+=1 if bleu>=4: trouve=2 return trouve else: rouge=0 bleu=0 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # teste les 6 diagonales croissantes : # test des 2 diagonales croissantes à 4 cases : rouge=[0,0] bleu=[0,0] for j in range(4): i=3-j k=i+2 l=j+3 if grille[i][j]==1: rouge[0]+=1 bleu[0]=0 if rouge[0]>=4: trouve=1 print("Bravo le joueur rouge à gagné") return trouve elif grille[i][j]==2: rouge[0]=0 bleu[0]+=1 if bleu[0]>=4: trouve=2 return trouve else: rouge[0]=0 bleu[0]=0 if grille[k][l]==1: rouge[1]+=1 bleu[1]=0 if rouge[1]>=4: trouve=1 print("Bravo le joueur rouge à gagné") return trouve elif grille[k][l]==2: rouge[1]=0 bleu[1]+=1 if bleu[1]>=4: trouve=2 return trouve else: rouge[1]=0 bleu[1]=0 # test des 2 diagonales croissantes à 5 cases : rouge=[0,0] bleu=[0,0] for j in range(5): i=4-j k=i+1 l=j+2 if grille[i][j]==1: rouge[0]+=1 bleu[0]=0 if rouge[0]>=4: trouve=1 print("Bravo le joueur rouge à gagné") return trouve elif grille[i][j]==2: rouge[0]=0 bleu[0]+=1 if bleu[0]>=4: trouve=2 return trouve else: rouge[0]=0 bleu[0]=0 if grille[k][l]==1: rouge[1]+=1 bleu[1]=0 if rouge[1]>=4: trouve=1 print("Bravo le joueur rouge à gagné") return trouve elif grille[k][l]==2: rouge[1]=0 bleu[1]+=1 if bleu[1]>=4: trouve=2 return trouve else: rouge[1]=0 bleu[1]=0 # test des 2 diagonales croissantes à 6 cases : rouge=[0,0] bleu=[0,0] for j in range(6): i=5-j k=i l=j+1 if grille[i][j]==1: rouge[0]+=1 bleu[0]=0 if rouge[0]>=4: trouve=1 print("Bravo le joueur rouge à gagné") return trouve elif grille[i][j]==2: rouge[0]=0 bleu[0]+=1 if bleu[0]>=4: trouve=2 return trouve else: rouge[0]=0 bleu[0]=0 if grille[k][l]==1: rouge[1]+=1 bleu[1]=0 if rouge[1]>=4: trouve=1 print("Bravo le joueur rouge à gagné") return trouve elif grille[k][l]==2: rouge[1]=0 bleu[1]+=1 if bleu[1]>=4: trouve=2 return trouve else: rouge[1]=0 bleu[1]=0 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # teste les 6 diagonales décroissantes : # test des 2 diagonales décroissantes à 4 cases : rouge=[0,0] bleu=[0,0] for j in range(3,7): i=j-3 k=j-1 l=i if grille[i][j]==1: rouge[0]+=1 bleu[0]=0 if rouge[0]>=4: trouve=1 print("Bravo le joueur rouge à gagné") return trouve elif grille[i][j]==2: rouge[0]=0 bleu[0]+=1 if bleu[0]>=4: trouve=2 return trouve else: rouge[0]=0 bleu[0]=0 if grille[k][l]==1: rouge[1]+=1 bleu[1]=0 if rouge[1]>=4: trouve=1 print("Bravo le joueur rouge à gagné") return trouve elif grille[k][l]==2: rouge[1]=0 bleu[1]+=1 if bleu[1]>=4: trouve=2 return trouve else: rouge[1]=0 bleu[1]=0 # test des 2 diagonales décroissantes à 5 cases : rouge=[0,0] bleu=[0,0] for j in range(2,7): i=j-2 k=j-1 l=i if grille[i][j]==1: rouge[0]+=1 bleu[0]=0 if rouge[0]>=4: trouve=1 print("Bravo le joueur rouge à gagné") return trouve elif grille[i][j]==2: rouge[0]=0 bleu[0]+=1 if bleu[0]>=4: trouve=2 return trouve else: rouge[0]=0 bleu[0]=0 if grille[k][l]==1: rouge[1]+=1 bleu[1]=0 if rouge[1]>=4: trouve=1 print("Bravo le joueur rouge à gagné") return trouve elif grille[k][l]==2: rouge[1]=0 bleu[1]+=1 if bleu[1]>=4: trouve=2 return trouve else: rouge[1]=0 bleu[1]=0 # test des 2 diagonales décroissantes à 6 cases : rouge=[0,0] bleu=[0,0] for j in range(1,7): i=j-1 k=i l=i if grille[i][j]==1: rouge[0]+=1 bleu[0]=0 if rouge[0]>=4: trouve=1 print("Bravo le joueur rouge à gagné") return trouve elif grille[i][j]==2: rouge[0]=0 bleu[0]+=1 if bleu[0]>=4: trouve=2 return trouve else: rouge[0]=0 bleu[0]=0 if grille[k][l]==1: rouge[1]+=1 bleu[1]=0 if rouge[1]>=4: trouve=1 print("Bravo le joueur rouge à gagné") return trouve elif grille[k][l]==2: rouge[1]=0 bleu[1]+=1 if bleu[1]>=4: trouve=2 return trouve else: rouge[1]=0 bleu[1]=0 # si on n'a rien trouvé on retourne 0 : return trouve # ############################################################################ # Pour l'IA # La fonction pions_rouges_alignes() teste si 2 ou 3 pions (n pions) rouges sont alignés dans la grille # afin de savoir où l'ordinateur (joueur BLEU) doit jouer # Si 3 pions sont alignés elle renvoie le numéro de la colonne suivante # Si rien n'est trouvé elle renvoie -1 def pions_rouges_alignes(n): trouve=-1 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # teste 4 pions alignés horizontalement en alanysant chacune des 6 lignes : for i in range(6): rouge=0 for j in range(7): if grille[i][j]==1: rouge+=1 if rouge==n: if i==5: # cas particulier de la première ligne if j!=6 and grille[i][j+1]==0: trouve=j+1 return trouve elif j==6 and grille[i][j-n]==0: trouve=j-n return trouve else: # une ligne haute if j!=6 and grille[i][j+1]==0 and grille[i+1][j+1]!=0: trouve=j+1 return trouve elif j==6 and grille[i][j-n]==0 and grille[i+1][j-n]!=0: trouve=j-n return trouve else: rouge=0 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # teste 4 pions alignés verticalement en alanysant chacune des 7 colonnes : for j in range(7): rouge=0 for i in range(6): if grille[5-i][j]==1: rouge+=1 if rouge==n and grille[4-i][j]==0: trouve=j return trouve else: rouge=0 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # teste les 6 diagonales croissantes : # test des 2 diagonales croissantes à 4 cases : rouge=[0,0] for j in range(4): i=3-j k=i+2 l=j+3 if grille[i][j]==1: rouge[0]+=1 if rouge[0]==n and i!=0 and grille[i-1][j+1]==0 and grille[i][j+1]!=0: trouve=j+1 return trouve else: rouge[0]=0 if grille[k][l]==1: rouge[1]+=1 if rouge[1]==n and k!=0 and l!=6 and grille[k-1][l+1]==0 and grille[k][l+1]!=0: trouve=l+1 return trouve else: rouge[1]=0 # test des 2 diagonales croissantes à 5 cases : rouge=[0,0] for j in range(5): i=4-j k=i+1 l=j+2 if grille[i][j]==1: rouge[0]+=1 if rouge[0]==n and i!=0 and grille[i-1][j+1]==0 and grille[i][j+1]!=0: trouve=j+1 return trouve else: rouge[0]=0 if grille[k][l]==1: rouge[1]+=1 if rouge[1]==n and k!=0 and l!=6 and grille[k-1][l+1]==0 and grille[k][l+1]!=0: trouve=l+1 return trouve else: rouge[1]=0 # test des 2 diagonales croissantes à 6 cases : rouge=[0,0] for j in range(6): i=5-j k=i l=j+1 if grille[i][j]==1: rouge[0]+=1 if rouge[0]==n and i!=0 and grille[i-1][j+1]==0 and grille[i][j+1]!=0: trouve=j+1 return trouve else: rouge[0]=0 if grille[k][l]==1: rouge[1]+=1 if rouge[1]==n and k!=0 and l!=6 and grille[k-1][l+1]==0 and grille[k][l+1]!=0: trouve=l+1 return trouve else: rouge[1]=0 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # teste les 6 diagonales décroissantes : # test des 2 diagonales décroissantes à 4 cases : rouge=[0,0] for j in range(3,7): i=j-3 k=j-1 l=i if grille[i][j]==1: rouge[0]+=1 if rouge[0]==n and i<=3 and j!=6 and grille[i+1][j+1]==0 and grille[i+2][j+1]!=0: trouve=j+1 return trouve else: rouge[0]=0 if grille[k][l]==1: rouge[1]+=1 if rouge[1]==n and k<=3 and l!=6 and grille[k+1][l+1]==0 and grille[k+2][l+1]!=0: trouve=l+1 return trouve else: rouge[1]=0 # test des 2 diagonales décroissantes à 5 cases : rouge=[0,0] for j in range(2,7): i=j-2 k=j-1 l=i if grille[i][j]==1: rouge[0]+=1 if rouge[0]==n and i<=3 and j!=6 and grille[i+1][j+1]==0 and grille[i+2][j+1]!=0: trouve=j+1 return trouve else: rouge[0]=0 if grille[k][l]==1: rouge[1]+=1 if rouge[1]==n and k<=3 and l!=6 and grille[k+1][l+1]==0 and grille[k+2][l+1]!=0: trouve=l+1 return trouve else: rouge[1]=0 # test des 2 diagonales décroissantes à 6 cases : rouge=[0,0] for j in range(1,7): i=j-1 k=i l=i if grille[i][j]==1: rouge[0]+=1 if rouge[0]==n and i<=3 and j!=6 and grille[i+1][j+1]==0 and grille[i+2][j+1]!=0: trouve=j+1 return trouve else: rouge[0]=0 if grille[k][l]==1: rouge[1]+=1 if rouge[1]==n and k<=3 and l!=6 and grille[k+1][l+1]==0 and grille[k+2][l+1]!=0: trouve=l+1 return trouve else: rouge[1]=0 # si on n'a rien trouvé on retourne -1 : return trouve # ############################################################################ # La fonction dessiner_boutons() dessine les boutons dans la zone interactive de la fenêtre de la tortue def dessiner_boutons(): # cache le curseur de la tortue : hideturtle() # vitesse maximale : speed(0) # configure la taille et la position de la fenêtre de la tortue dans l'écran : setup(1000,430,0,0) # titre de la fenêtre : title("Puissance 4") color("black") up() goto(x_base+8*largeur,y_base) down() setheading(0) for i in range(2): fd(200) lt(90) fd(50) lt(90) up() goto(x_base+8*largeur+20,y_base+10) down() write("Quitter",font=('Arial Unicode MS', 18)) up() goto(x_base+8*largeur,y_base+65) down() setheading(0) for i in range(2): fd(200) lt(90) fd(50) lt(90) up() goto(x_base+8*largeur+20,y_base+75) down() write("Recommencer",font=('Arial Unicode MS', 18)) up() goto(x_base+8*largeur+250,y_base+200) down() setheading(0) for i in range(2): fd(200) lt(90) fd(50) lt(90) up() goto(x_base+8*largeur+270,y_base+210) down() write("Sauvegarder",font=('Arial Unicode MS', 18)) up() goto(x_base+8*largeur+250,y_base+135) down() setheading(0) for i in range(2): fd(200) lt(90) fd(50) lt(90) up() goto(x_base+8*largeur+270,y_base+145) down() write("Restaurer",font=('Arial Unicode MS', 18)) up() goto(x_base+8*largeur+20,y_base+300) down() write("Le joueur ROUGE commence",font=('Arial Unicode MS', 18)) up() goto(x_base+8*largeur+50,y_base+270) down() write("Utiliser le clique droit pour intéragir avec les boutons",font=('Arial Unicode MS', 15)) # # ############################################################################ # La fonction dessiner_pion(x,y,couleur) ajoute un pion dans la case (x,y) def dessiner_pion(x,y,couleur): global joueur_courant # x de 0 à 6 et y de 0 à 5 up() goto(x_base+(x+1)*largeur-largeur//8,y_base+(y+1)*largeur-largeur//2) down() if couleur==1: # pion ROUGE si couleur=1 : color('red') else: # pion BLEU si couleur=2 : color('blue') begin_fill() circle(largeur/2.5) end_fill() pions_alignes() # ############################################################################ # La fonction recommencer est appelée si on appuie sur la touche Echap def recommencer(): # utilise les variables globales pour les modifier : global grille,liste_colonne,joueur_courant # efface la fenêtre de la tortue : reset() # dessine les boutons dessiner_boutons() # dessine la grille vide : dessiner_grille() # ré-initialise les variables globales pour définir une grille vide : grille=[7*[0], 7*[0], 7*[0], 7*[0], 7*[0], 7*[0]] liste_colonne=7*[0] joueur_courant=1 # Affiche le séparateur et le message dans la console : print('\n\n==========================================================\n\n') print("Vous venez d'appuyer sur Echap : la partie recommence à zéro") print('La grille est vide et le joueur ROUGE commence :') # affiche la grille dans la console : afficher_grille() print('\n\n\n\n\n\n=============================================') print(' PUISSANCE 4 : FINIR UNE PARTIE') print('=============================================') if joueur_courant==1: joueur='ROUGE' else: joueur='BLEU' print("\nL'état de la partie vient d'être restaurée à partir du fichier grille.txt.") print("C'est au joueur %s à jouer." % joueur) afficher_grille() def bouton_clique(x, y): bouton_recommencer =(x_base+8*largeur,y_base+65, 200, 50) bouton_quitter = (x_base + 8 * largeur, y_base, 200, 50) bouton_sauvegarder = (x_base+8*largeur+270,y_base+210, 200, 50) bouton_restaurer = (x_base+8*largeur+250,y_base+135, 200, 50) if bouton_quitter[0] <= x <= bouton_quitter[0] + bouton_recommencer[2] and\ bouton_quitter[1] <= y <= bouton_quitter[1] + bouton_recommencer[3]: print("Quitter, fin de la partie") bye() if bouton_recommencer[0] <= x <= bouton_recommencer[0] + bouton_recommencer[2] and\ bouton_recommencer[1] <= y <= bouton_recommencer[1] + bouton_recommencer[3]: print ("Recommencer, nouvelle partie en cours") print("Type de bouton_sauvegarder :", type(bouton_sauvegarder)) print("Valeur de bouton_sauegarder :", bouton_sauvegarder) recommencer() if bouton_sauvegarder[0] <= x <= bouton_sauvegarder[0] + bouton_sauvegarder[2] and\ bouton_sauvegarder[1] <= y <= bouton_sauvegarder[1] + bouton_sauvegarder[3]: print("Partie sauvegardé") sauvegarde() if bouton_restaurer[0] <= x <= bouton_restaurer[0] + bouton_restaurer[2] and\ bouton_restaurer[1] <= y <= bouton_restaurer[1] + bouton_restaurer[3]: print("Partie restauré") restaure() # ######## def sauvegarde(): import sqlite3 fic_db = sqlite3.connect('partie.db') obj_db = fic_db.cursor() obj_db.execute(''' CREATE TABLE IF NOT EXISTS users ( c1 INTEGER NOT NULL, c2 INTEGER NOT NULL, c3 INTEGER NOT NULL, c4 INTEGER NOT NULL, c5 INTEGER NOT NULL, c6 INTEGER NOT NULL, c7 INTEGER NOT NULL ) ''') for ligne in grille: obj_db.execute('INSERT INTO users (c1, c2, c3, c4, c5, c6, c7) VALUES (?, ?, ?, ?, ?, ?, ?)', (ligne[0], ligne[1], ligne[2], ligne[3], ligne[4], ligne[5], ligne[6])) print("Partie sauvegardé") fic_db.commit() fic_db.close() # def restaure(): import sqlite3 # Connexion à la base de données transférée fic_db = sqlite3.connect('partie.db') objt_db = fic_db.cursor() # Lecture des données objt_db.execute('SELECT * FROM users') tableau = objt_db.fetchall() grille=[] # Affichage des données for ligne in tableau: print(ligne) grille.append(list(ligne)) print("Partie restaurer") print('\nGrille :', grille) # Fermeture de la connexion fic_db.close() # efface la fenêtre de la tortue : reset() # dessine les boutons dessiner_boutons() # dessine la grille vide : dessiner_grille() # ré-initialise les variables globales pour définir une grille vide : tab_colonne=7*[0] for i in range(6): for j in range(7): if grille[i][j]!=0: tab_colonne[j]+=1 dessiner_pion(j,5-i,grille[i][j]) afficher_grille() # ############################################################################ # P R O G R A M M E P R I N C I P A L # ############################################################################ # initialise l'affichage graphique de la grille : # Largeur règle la largeur des cases et la taille des pions fini=0 largeur=55 trouve=0 # x_base et y_base règle la position de la grille dans la fenêtre de la tortue x_base=-450 y_base=-160 # dessine les boutons : dessiner_boutons() # dessine la grille vide : dessiner_grille() print('Cliquez dans une colonne pour jouer ou Appuyer sur Echap pour recommencer une partie.') print('Le nom des joueurs sera ici ROUGE et BLEU. Le joueur ROUGE commence.') print('Début de la partie (la grille est vide) :') # affiche la grille dans la console : afficher_grille() # demande le nom de chaque joueur : nom_joueur_bleu=textinput("Bleu","Entrez le nom du joueur BLEU") nom_joueur_rouge=textinput("Rouge","Entrez le nom du joueur ROUGE") # fonction à lancer si on clique avec un bouton de la souris : onscreenclick(jouer) # clic gauche onscreenclick(bouton_clique, 3) # lance le gestionnaire d'évènement qui détecte les évèvements de la souris : listen() # lance la boucle principale : done() # ############################################################################ # F I N D U P R O G R A M M E # ############################################################################