J'ai tenté de reproduire le célèbre Motus télévisé en Python2.6
Faites moi part de vos suggestions d'amélioration et critiques quant au code.
J'ai scindé le travail en 2 parties : le programme principal et 1 classe pour les grilles qui contiennent
les fameuses boules jaunes et noires.
En espérant qu'il ne reste pas trop de bugs.
Cordialement.
Mints.
Source / Exemple :
# -*- coding:UTF-8 -*-
################################################################################
# #
# Motux #
# #
# Motus'like game #
# version 1.2 #
# language : Python 2.6 #
# auteur : Guillaume Michon #
# date : 14/10/2012 #
# #
################################################################################
from Tkinter import *
import tkSnack
from grilleLoto2 import *
#-------------------------------------------------------------------------------
def NouvellePartie(fichierMots):
"""Appelle la fonction de chargement de mots.
Crée l'espace de jeu.
Appel l'initialisation des grilles de loto.
Donne la main au joueur 1 par défaut."""
global tableauDeCanevas,equipeCourante,airDessin
Charger(fichierMots)
airDessin.destroy() # A chaque nouvelle partie on supprime cette Frame contenant les canvas
airDessin = Frame(fen) # pour en recréer une autre en fonction du nouveau nombre de lettres
# Remplissage du tableau de canvas
tableauDeCanevas = []
for ligne in range(6):
tabCanvasLigne = []
for colonne in range(nbrLettres):
canvas = Canvas(airDessin,bg='blue',height=50,width=50,borderwidth=5,relief='ridge')
canvas.grid(row=ligne,column=colonne)
tabCanvasLigne.append(canvas)
tableauDeCanevas.append(tabCanvasLigne)
airDessin.grid(row=1,column=1)
# Reinitialisation des grilles des joueurs
for equipe in equipes:
equipe.score = 00
equipe.labelScore.configure(text="Score : "+str(equipe.score))
equipe.labelEquipe.configure(text=" ")
equipe.configure(bg='white')
equipe.Reinitialiser()
equipe.boutonTirage.config(state='disable')
equipeCourante = 0 # equipe qui a la main
equipes[equipeCourante].labelEquipe.configure(text=" A VOUS !")
equipes[equipeCourante].configure(bg='maroon')
NouveauMot()
def Charger(fichier_mots):
"""Charge le fichier de mots correspondant au nombre de lettres désiré
dans une liste primaire qui permettra de vérifier si le mot tapé existe,
et dans une liste secondaire de laquelle il sera retiré pour éviter les répétitions."""
global listeMots, listeSecondaire,nbrLettres
fichier = open(fichier_mots,'r')
listeMots = []
while 1:
mot = fichier.readline()
if mot == "":
break
listeMots.append(mot[:-1])
nbrLettres = len(listeMots[0])
listeSecondaire = listeMots[:]
fichier.close()
def SelectionMot():
"""Sélectionne un mot au hazard dans la liste de mots chargé et
le retire de la liste secondaire pour éviter les répétitions."""
global listeSecondaire
hazard = randrange(0,len(listeSecondaire))
motA_Trouver = listeSecondaire[hazard]
del listeSecondaire[hazard]
if not listeSecondaire:
listeSecondaire = listeMots[:]
return motA_Trouver
#-------------------------------------------------------------------------------
def NouveauMot():
"""Initialisation de toutes les variables de la grille de jeu lors de la recherche d'un nouveau mot."""
global enigme,proposition,ligneCourante,colonneCourante,lettresBienPlacees,tableauDePropositions
enigme = SelectionMot() # le mot à trouver
print enigme
proposition = '' # chaque lettre tappée viendra s'ajouter a cette chaîne de caractères
ligneCourante, colonneCourante = 0, 0 # coordonnées permettant de se déplacer dans le tableau de canvas
# tableau qui contiendra toutes les lettres bien placées depuis le debut de la recherche
lettresBienPlacees = ['']*nbrLettres
# tableau qui contiendra toutes les propositions faites depuis le debut de la recherche
tableauDePropositions = []
EffaceCanevas() # On efface tous les canvas
sonNouveauMot.play()
lettresBienPlacees[0] = enigme[0] # la 1ère lettre du mot à trouver est toujours considérée comme bonne
AttenteProposition() # on l'affiche et on donne la main au joueur
def EffaceCanevas():
"""Efface et remet en bleu tous les canvas présents dans l'air de jeu."""
for ligne in range(6):
for colonne in range(nbrLettres):
tableauDeCanevas[ligne][colonne].delete(ALL)
tableauDeCanevas[ligne][colonne].configure(bg="blue")
#-------------------------------------------------------------------------------
def AttenteProposition():
"""Mise à jour de la ligne courante de la grille de jeu.
Toutes les lettres bien placées au fur et à mesure des essaies
ont été mémorisées dans lettresBienPlacees[], c'est ici qu'on les affiche.
Liaison du clavier sur fonction LettreTapee."""
compt = 0
while compt < len(lettresBienPlacees) :
couleur = 'blue'
if lettresBienPlacees[compt] != '':
couleur = 'red'
tableauDeCanevas[ligneCourante][compt].delete(ALL)
tableauDeCanevas[ligneCourante][compt].create_text(30,30,font='Century 28 bold ',text=lettresBienPlacees[compt])
tableauDeCanevas[ligneCourante][compt].configure(bg=couleur)
compt += 1
fen.bind('<Key>',LettreTapee)
def LettreTapee(event):
"""Récupération de la lettre tapée(conversion en majuscule) et constitution de la proposition du joueur.
Vérification de la position dans la grille de jeu."""
global ligneCourante,colonneCourante,proposition,tableauDePropositions,correspondance
tableauDeCanevas[ligneCourante][colonneCourante].delete(ALL)
c = str.upper(event.char)
if str.isalpha(c):
# si la touche clavier est une lettre elle est ajoutée à la chaîne de caractères 'proposition' et l'indice colonneCourante est incrémenté
proposition += c
# et ce tant que celui-ci est inférieur aux nombres de lettres du mot recherché
if colonneCourante < nbrLettres:
tableauDeCanevas[ligneCourante][colonneCourante].create_text(30,30,font='Century 28 bold ',text=c)
tableauDeCanevas[ligneCourante][colonneCourante].configure(bg='purple')
colonneCourante += 1
# le nombre de lettres est atteint
if colonneCourante == nbrLettres:
correspondance = [] # contient les couples [lettre de l'essaie,chiffre correspondant] où chiffre correspondant pourra prendre
for lettre in proposition: # 3 valeurs : 0 si lettre absente ; 1 si bien placée ; 2 si mal placée
correspondance.append([lettre,0]) # par défaut on considère toutes les lettre mal placées
tableauDePropositions.append(correspondance) # on ajoute cette correspondance au tableau total
if proposition not in listeMots: # on vérifie si le mot entré est correct
sonMotErrone.play()
proposition = '' # dans le cas contraire on reinit la proposition
MajPropositions() # on réaffiche toutes les propositions
LaMainPasse() # et la main passe
if ligneCourante != 5: # si on n'est pas sur la dernière ligne
ligneCourante += 1 # on descend
AttenteProposition() # et on attend la futur proposition
else:
AttenteProposition() # sinon on ne descend pas mais
Aide() # on affiche une lettre non bien placée jusqu'à présent
colonneCourante = 0
return
# le mot existe mais est-ce le bon ? la Verification nous renvera 'False' dans la négative
elif not Verification(correspondance) :
proposition = '' # auquel cas on reinit la proposition
MajPropositions() # on réaffiche toutes les propositions
if ligneCourante != 5: # si on n'est pas sur la dernière ligne
ligneCourante += 1 # on descend
AttenteProposition() # et on attend la futur proposition
else: # si on n'est pas sur la dernière ligne
LaMainPasse() # la main passe
AttenteProposition() #on attend la futur proposition
Aide() # on affiche une lettre non bien placée jusqu'à présent
colonneCourante = 0
return
#-------------------------------------------------------------------------------
def Verification(correspondance):
"""Algorithme principal
Pour des raisons d'affichage et sonore le mot tapé est entré dans un tableau
de correspondance du type :
[['lettre1',chiffre correspondant],['lettre2',chiffre correspondant],[]...]
où chiffre correspondra à une couleur et un effet sonore lors de l'animation de la proposition.
Le mot recherché(enigme) est transformé en liste : resteEnigme
Dans un premier temps on compare les lettres du mot tapé et du mot à découvrir 2 à 2.
Si il y a correspondance, le chiffre de ces lettres passe à 1 dans 'correspondance' et on les remplace dans la liste resteEnigme
par des espaces pour signifier au reste de l'algorithme que la lettre n'est plus à prendre en compte et pour conserver le même
nombre de lettres et éviter ainsi les décalage.
On en profite pour remplir le tableau des lettres bien placées 'lettresBienPlacees' et on incrémente
une variable locale 'lettresBienTapees'.Si celle-ci équivaut au nombre de lettres de l'enigme la solution est trouvée.
Dans le cas contraire on compare succesivement chaque lettre de 'correspondance' dont le chiffre est different de 1 avec toutes celles restant
dans resteEnigme.Lorsqu'il y a correspondance le chiffre de cette lettre passe à 2 et elle est remplacée par un espace dans resteEnigme.
On a ainsi trouvé toutes les lettres présentes mais mal placées."""
fen.unbind('<Key>')
resteEnigme = list(enigme)
compt = 0
lettresBienTapees = 0
while(compt < nbrLettres):
#Lettres bien placées
if correspondance[compt][0] == resteEnigme[compt]:
correspondance[compt][1] = 1
resteEnigme[compt] = " "
lettresBienPlacees[compt] = enigme[compt]
lettresBienTapees += 1
compt += 1
# Le mot est trouvé
if lettresBienTapees == nbrLettres:
MotTrouve()
return True # On présice à la méthode appelante 'LettreTapee' que le mot est trouvé
# Lettres présentes mais mal placées
for couple in correspondance:
if couple[1] == 1:
continue
for lettre in resteEnigme:
if couple[0] == lettre:
couple[1] = 2
resteEnigme[resteEnigme.index(lettre)] = " "
break
# On anime chaque lettre de la proposition
for indexColonne in range(nbrLettres):
fen.after(350,AnimationProposition(indexColonne,correspondance[indexColonne][0],correspondance[indexColonne][1]))
return False # On présice à la méthode appelante 'LettreTapee' que le mot n'est pas trouvé
#-------------------------------------------------------------------------------
def AnimationProposition(indexColonne=None,lettre=None,couleurEtSon=None):
"""Fonction qui écrie une lettre dans le canvas de coordonnée [ligneCourante][colonneCourante] dans le tableau de canvas."""
# On retrouve ici les 3 actions distinctes à effectuer pour chaque lettre de la proposition du joueur
if couleurEtSon == 1:
couleur = 'red'
son = beepRouge
elif couleurEtSon == 2:
couleur = 'yellow'
son = beepJaune
elif couleurEtSon == 0:
couleur = 'blue'
son = beepBleu
son.play()
tableauDeCanevas[ligneCourante][indexColonne].configure(bg=couleur)
tableauDeCanevas[ligneCourante][indexColonne].create_text(30,30,font='Century 28 bold ',text=lettre)
fen.update()
#-------------------------------------------------------------------------------
def MajPropositions():
"""Toutes les propositions ont été morisées dans le tableau tableauDePropositions.
C'est ici qu'elles sont affichées.Si leur nombre dépasse 5, on copie le tableau sur lui même en enlevant la 1ère."""
global tableauDePropositions
EffaceCanevas()
if len(tableauDePropositions) == 6:
tableauDePropositions = tableauDePropositions[1:]
ligne = 0
for proposition in tableauDePropositions:
for colonne in range(nbrLettres):
if proposition[colonne][1] == 1:
couleur = 'red'
elif proposition[colonne][1] == 2:
couleur = 'yellow'
elif proposition[colonne][1] == 0:
couleur = 'blue'
tableauDeCanevas[ligne][colonne].create_text(30,30,font='Century 28 bold ',text=proposition[colonne][0])
tableauDeCanevas[ligne][colonne].configure(bg=couleur)
ligne += 1
#-------------------------------------------------------------------------------
def Aide():
"""Appelée en guise d'aide sur la dernière ligne de jeu pour afficher
la première lettre non trouvée après que la main soit passée."""
fen.unbind('<Key>')
sonAide.play()
compt = 0
while compt < nbrLettres:
if lettresBienPlacees[compt] == '':
lettresBienPlacees[compt] = enigme[compt]
for j in range(5):
fen.after(100,AnimationAide(compt,lettresBienPlacees[compt],'red'))
fen.after(100,AnimationAide(compt,'','blue'))
tableauDeCanevas[ligneCourante][compt].configure(bg='red')
tableauDeCanevas[ligneCourante][compt].create_text(30,30,font='Century 28 bold ',text=lettresBienPlacees[compt])
break
compt += 1
fen.bind('<Key>',LettreTapee)
def AnimationAide(indexColonne,lettre,couleur):
tableauDeCanevas[ligneCourante][indexColonne].configure(bg=couleur)
tableauDeCanevas[ligneCourante][indexColonne].create_text(30,30,font='Century 28 bold ',text=lettre)
fen.update()
#-------------------------------------------------------------------------------
def MotTrouve():
"""Mise à jour du score et animation du mot trouvé."""
fen.unbind('<Key>')
for indexColonne in range(nbrLettres):
fen.after(350,AnimationProposition(indexColonne,correspondance[indexColonne][0],correspondance[indexColonne][1]))
equipes[equipeCourante].score += 50
equipes[equipeCourante].labelScore.configure(text="Score : "+str(equipes[equipeCourante].score))
sonMotTrouve.play()
for j in range(3):
for i in range(nbrLettres):
fen.after(50,AnimationMotTrouve(i,'green'))
for i in range(nbrLettres):
fen.after(50,AnimationMotTrouve(i,'red'))
equipes[equipeCourante].boutonTirage.config(state='active')
TirageBoules()
def AnimationMotTrouve(indexColonne,couleur):
tableauDeCanevas[ligneCourante][indexColonne].configure(bg=couleur)
fen.update()
#-------------------------------------------------------------------------------
def TirageBoules():
"""Un appel récurssif de cette fonction nous donne l'etat des membres des
instances de GrilleLoto à chaque instant.3 cas possibles :
1/ il y a motux
2/ boule noire tirée
3/ 2 boules jaunes tirées"""
if equipes[equipeCourante].yaMotux and equipes[equipeCourante].finAnimationMotux:
equipes[equipeCourante].score += 100
equipes[equipeCourante].labelScore.configure(text="Score : "+str(equipes[equipeCourante].score))
for equipe in equipes:
equipe.yaMotux = False
equipe.finAnimationMotux = False
equipe.boutonTirage.config(state='disable')
for equipe in equipes:
equipe.Reinitialiser()
fen.after(1000,NouveauMot)
return
if equipes[equipeCourante].bouleNoireTiree :
equipes[equipeCourante].boutonTirage.config(state='disable')
equipes[equipeCourante].bouleNoireTiree = False
equipes[equipeCourante].nbrBoulesJaunesTirees = 0
fen.after(1000,LaMainPasse)
fen.after(1000,NouveauMot)
return
if equipes[equipeCourante].nbrBoulesJaunesTirees == 2 and not equipes[equipeCourante].yaMotux:
equipes[equipeCourante].nbrBoulesJaunesTirees = 0
fen.after(1000,NouveauMot)
return
fen.after(50,TirageBoules)
#-------------------------------------------------------------------------------
def LaMainPasse():
"""Fonction qui met a jour les grilles de loto et qui passe la main à l'autre joueur."""
global equipes, equipeCourante
equipes[equipeCourante].labelEquipe.configure(text=" ")
equipes[equipeCourante].configure(bg='white')
equipeCourante += 1
if equipeCourante == 2:
equipeCourante = 0
equipes[equipeCourante].labelEquipe.configure(text=" A VOUS !")
equipes[equipeCourante].configure(bg='maroon')
#-------------------------------------------------------------------------------
def Presentation():
"""Ecrit le mot "MOTUX" sur toutes les lignes de la grille de jeu instanciation de 2 GrilleLoto."""
global airDessin,equipes
motux = "MOTUX"
tableauDeCanevas = []
nbrLettres = 5
airDessin = Frame(fen)
tableauDeCanevas = []
for x in range(6):
tabCanvasLigne = []
for y in range(nbrLettres):
canvas = Canvas(airDessin,bg='blue',height=50,width=50,borderwidth=5,relief='ridge')
canvas.create_text(30,30,font='Century 28 bold ',text=motux[y])
canvas.grid(row=x,column=y)
tabCanvasLigne.append(canvas)
tableauDeCanevas.append(tabCanvasLigne)
airDessin.grid(row=1,column=1)
numerosGrille1 = ['7','17','35','49','57','11','25','29','51','59','3','19','41','43','69','5','21','33','53','63','9','23','37','45','61']
numerosGrille2 = ['12','26','40','52','60','10','22','30','46','58','8','18','32','44','70','6','16','38','54','62','2','20','36','56','66']
equipes = []
equipes.append(GrilleLoto(numerosGrille1))
equipes[0].grid(row=1,column=0)
equipes.append(GrilleLoto(numerosGrille2))
equipes[1].grid(row=1,column=2)
#-------------------------------------------------------------------------------
def Quitter():
fen.quit()
fen.destroy()
#-------------------------------------------------------------------------------
fen = Tk()
fen.title("Motux")
fen.resizable(0,0)
barreMenu = Menu(fen)
options=Menu(barreMenu)
barreMenu.add_cascade(label="Nouvelle Partie",menu=options)
options.add_command(label = "Mots de 6 lettres",command=lambda : NouvellePartie("mots6.txt"))
options.add_command(label = "Mots de 7 lettres",command=lambda : NouvellePartie("mots7.txt"))
options.add_command(label = "Mots de 8 lettres",command=lambda : NouvellePartie("mots8b.txt"))
options.add_command(label = "Quiter",command=Quitter)
fen.config(menu=barreMenu)
tkSnack.initializeSnack(fen)
sonNouveauMot = tkSnack.Sound(file='nouveau_mot.wav')
sonAide = tkSnack.Sound(file='aide.wav')
sonMotTrouve = tkSnack.Sound(file='kultur0407.wav')
sonMotErrone = tkSnack.Sound(file='incorrect.wav')
beepRouge = tkSnack.Sound(file='beep-3.wav')
beepJaune = tkSnack.Sound(file='beep-6.wav')
beepBleu = tkSnack.Sound(file='beep-4.wav')
Presentation()
fen.mainloop()
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.