""" PROJET NSI GROUPE : KELLIAN BITROU, ILHAN COULIBALY, ADRIEN VIGEANT DATE : MAI 2025 THEME : MORPION VERSION : 2 (Avec IA) Kellian : - Tracé de la grille - Définition de la fenêtre - Gestion de l'interface (message de victoire) - Dessin des X et des O - Puis aide sur les erreurs Python et aide aux autres membres du groupe Ilhan : - Gestion de l'interactivité - Où afficher les X et les O - Vérification pour les coordonées pour ne pas dessiner hors de la grille - Système de sauvegarde de la partie et chargement d'une partie sauvegardée Adrien : - Gestion de l'IA - Dans une version antérieure d'abord aléatoire, dans la version actuelle réfléchie et qui joue le meilleur coup - Gestion des conditions de victoire - Arrêter le jeu une fois qu'un joueur à gagné - Aide sur le système de chargement d'une partie sauvegardée FONCTIONS RÉALISÉES : Tracer la grille, affichage des X et O, gestion de la victoire, coupure du jeu quand un joueur à gagné, Intelligence Artificielle qui répond aux coups du joueur humain FONCTIONS NON RÉALISÉES : Jeu en réseau, choix de jouer en joueur contre joueur ou en joueur contre IA, annonce de l'égalité """ from turtle import * from random import choice import sqlite3 # VARIABLE QUI VÉRIFIE SI LA PARTIE EST FINIE jeu_fini = False # INITIALISATION DE LA FENÊTRE TURTLE def afficher_grille(): setup(1600, 1000) speed(0) up() hideturtle() goto(0, 400) down() write("Cliquez gauche dans une case pour jouer. L'IA jouera automatiquement.", align='center') # Lignes horizontales for i in range(4): up() goto(-300, -300 + 200 * i) down() forward(600) left(90) # Lignes verticales for i in range(4): up() goto(-300 + 200 * i, -300) down() forward(600) def effacer_grille(): # cette fonction est appelée si on clique sur le bouton droit de la souris global grille reset() clear() afficher_grille() grille=[[0,0,0],[0,0,0],[0,0,0]] # EFFACE LES MESSAGES DE L'INTERFACE def effacer_message(): up() goto(-400, 250) down() color("white") write(" ", font=("Arial", 16, "normal")) # AFFICHE UN MESSAGE DE VICTOIRE SUR LE CÔTÉ GAUCHE def afficher_victoire(message): color("black") up() goto(-600, 250) down() write(message, font=("Arial", 16, "normal")) # VÉRIFIE S'IL Y A UN GAGNANT def verifier_gagnant(): for i in range(3): if grille[i][0] == grille[i][1] == grille[i][2] != 0: return grille[i][0] for i in range(3): if grille[0][i] == grille[1][i] == grille[2][i] != 0: return grille[0][i] if grille[0][0] == grille[1][1] == grille[2][2] != 0: return grille[0][0] if grille[0][2] == grille[1][1] == grille[2][0] != 0: return grille[0][2] return None # DESSINE UN ROND A LA CASE CHOISIE PAR L'IA def dessiner_rond(i, j): color("blue") x = -226 + j * 200 y = 155 - i * 200 up(); goto(x, y); down(); write('O', font=('Arial Unicode MS', 55)) # L'IA JOUE def jouer_IA(): # Si le jeu est déjà terminé, on ne fait rien global jeu_fini if jeu_fini: return # Essaye de gagner move = trouver_meilleur_coup(2) if not move: # Essaye de bloquer le joueur move = trouver_meilleur_coup(1) if not move: # Prendre le centre if grille[1][1] == 0: move = (1, 1) if not move: # Sinon case vide aléatoire cases_vides = [(i, j) for i in range(3) for j in range(3) if grille[i][j] == 0] if cases_vides: move = choice(cases_vides) if move: i, j = move grille[i][j] = 2 dessiner_rond(i, j) gagnant = verifier_gagnant() if gagnant == 2: afficher_victoire("L'IA (O) a gagné!") global jeu_fini jeu_fini = True return True return False # L'IA TROUVE LE MEILLEUR COUP def trouver_meilleur_coup(joueur): # Vérifie lignes, colonnes, diagonales for i in range(3): if grille[i].count(joueur) == 2 and grille[i].count(0) == 1: return (i, grille[i].index(0)) # Ligne for j in range(3): col = [grille[i][j] for i in range(3)] if col.count(joueur) == 2 and col.count(0) == 1: return (col.index(0), j) # Colonne diag1 = [grille[i][i] for i in range(3)] if diag1.count(joueur) == 2 and diag1.count(0) == 1: idx = diag1.index(0) return (idx, idx) diag2 = [grille[i][2 - i] for i in range(3)] if diag2.count(joueur) == 2 and diag2.count(0) == 1: idx = diag2.index(0) return (idx, 2 - idx) return None # GESTION CLIC HUMAIN def cliquer_gauche(x, y): global jeu_fini if jeu_fini: return # Le jeu est terminé, ne fait rien si le joueur clique color("red") positions = [ (-300, -100, 100, 300), # (x1, x2, y1, y2) (-100, 100, 100, 300), (100, 300, 100, 300), (-300, -100, -100, 100), (-100, 100, -100, 100), (100, 300, -100, 100), (-300, -100, -300, -100), (-100, 100, -300, -100), (100, 300, -300, -100) ] coords = [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)] centers = [(-226, 155), (-26, 155), (174, 155), (-226, -55), (-26, -55), (174, -55), (-226, -255), (-26, -255), (174, -255)] for idx, (x1, x2, y1, y2) in enumerate(positions): if x1 < x < x2 and y1 < y < y2: i, j = coords[idx] if grille[i][j] != 0: print("Case déjà occupée") return up(); goto(centers[idx]); down(); write('\u2715', font=('Arial Unicode MS', 55)) grille[i][j] = 1 print(grille) gagnant = verifier_gagnant() if gagnant == 1: afficher_victoire("Le joueur (X) a gagné!") global jeu_fini jeu_fini = True return # Effacer le message avant de jouer l'IA effacer_message() if jouer_IA(): return print("Clique en dehors de la grille") # ENREGISTRER LA PARTIE def enregistrement(): # Connexion à la base de données (ou création si elle n'existe pas) conn = sqlite3.connect('morpion.bd') cursor = conn.cursor() cursor = conn.cursor() grille_jeu=grille # Création d'une table cursor.execute(''' CREATE TABLE IF NOT EXISTS users ( c1 INTEGER NOT NULL, c2 INTEGER NOT NULL, c3 INTEGER NOT NULL ) ''') # Insertion de quelques données for ligne in grille: cursor.execute('INSERT INTO users (c1,c2,c3) VALUES (?,?,?)', (ligne[0],ligne[1],ligne[2])) # Validation des modifications conn.commit() # Fermeture de la connexion conn.close() # CHARGEMENT DE LA SAUVEGARDE def charger_sauvegarde(): global grille, jeu_fini try: conn = sqlite3.connect('morpion.bd') cursor = conn.cursor() # Lire les 3 premières lignes cursor.execute("SELECT * FROM users LIMIT 3") lignes = cursor.fetchall() if len(lignes) != 3: print("Sauvegarde invalide.") return grille = [list(ligne) for ligne in lignes] # Réinitialiser l'affichage reset() clear() afficher_grille() # Redessiner X et O en fonction de la grille for i in range(3): for j in range(3): if grille[i][j] == 1: color('red') x = -226 + j * 200 y = 155 - i * 200 up(); goto(x, y); down(); write('\u2715', font=('Arial Unicode MS', 55)) elif grille[i][j] == 2: dessiner_rond(i, j) gagnant = verifier_gagnant() if gagnant: message = "Le joueur (X) a gagné!" if gagnant == 1 else "L'IA (O) a gagné!" afficher_victoire(message) jeu_fini = True conn.close() except Exception as e: print("Erreur lors du chargement :", e) #=============================================================================== # PROGRAMME PRINCIPAL #=============================================================================== grille = [[0, 0, 0], [0, 0, 0], [0, 0, 0]] afficher_grille() onscreenclick(cliquer_gauche) onkeypress(enregistrement,"e") onkeypress(charger_sauvegarde, "c") listen() done()