Author: Raphael C.

Projets

Le jeu du motus en python

MOTUS est à l’origine un jeu télévisé diffusé entre 1990 et 2019 sur France 2. Ce programme d’origine américaine s’inspire du jeu MasterMind, les lettres ayant remplacés les chiffres. Ce jeu a connu depuis de nombreuses variantes dont le célèbre WORDLE qui connait un très grand succès actuellement sur internet.

Introduction

Les règles du jeu sont plutôt simples : l’objectif est de trouver un mot d’un nombre fixé de lettres en au plus 6 essais. La première lettre du mot à découvrir est donnée et après chaque tentative :

  • les lettres communes et bien placées sont signalées par une case rouge
  • les lettres communes mais mal placées sont, quant à elles, signalées par une case jaune

Si le joueur parvient à découvrir le mot avant les 6 essais, il remporte la partie, sinon ce mot lui est dévoilé.

Certaines versions du jeu, dont WORDLE, se jouent à une personne, même si à l’origine le jeu télévisé se joue à deux. Dans la version à 2 joueurs, aux règles précédentes s’ajoutent les suivantes : un joueur perd la main si le mot proposé :

  • n’est pas de la bonne longueur
  • ne commence pas par la lettre proposée
  • est mal épelé
  • n’est pas donné dans les 8 secondes imparties
  • ne figure pas dans le dictionnaire
  • n’a pas été trouvé au terme des 6 essais

Dans chacun de ces cas, le joueur adverse récupère la main et bénéficie d’une lettre bonus : la première lettre non découverte lui est dévoilée. Il dispose alors du nombre d’essais restants (du joueur précédent) pour trouver le mot. Dans le cas ou il ne dispose que d’une tentative pour découvrir le mot, il conserve la main pour la grille suivante même en cas d’échec.

Notre projet est donc de programmer en langage python ce jeu. D’une part parce que nous aimons bien jouer à WORDLE (nous avons découvert le jeu original en visionnant une partie sur Youtube) et d’autre part car la programmation de ce jeu nous semblait accessible (pour notre niveau) sans être trop simple et offrait de nombreuses possibilités d’évolutions et améliorations (mode 2 joueurs, prise en compte de règles supplémentaires, interface graphique).

La première question qui s’est naturellement posée dès le départ concernait le choix de l’interface : en mode console ou plutôt avec une interface graphique ? Après une mure réflexion et avoir consulté plusieurs sites notamment de NSI, nous nous sommes rendus à l’évidence : une interface graphique nécessitait un passage obligé par le module tkinter particulièrement adapté à ce jeu. Et même si ce module semble accessible pour les novices que nous sommes, nous avons jugé plus prudent dans un premier temps, de travailler sur un jeu en mode console.

Après avoir réfléchi à la structure de notre programme, nous avons écrit ensemble les différentes fonctions que devra utiliser le jeu. Puis, comme il nous restait du temps, nous avons décidé de programmer à partir de ces fonctions, deux modes de jeu : un mode 1 joueur et un mode à 2. Nous nous sommes répartis le travail et chacun de nous a développé son propre mode et nous les avons assemblés dans le programme final.

Notre programme

Nous avons essayé de rester les plus fidèles au jeu original même si comme nous le verrons plus tard, nous n’avons pas implémenté toutes les règles présentées précedemment.

Concernant l’affichage, avant que le joueur ne fasse sa proposition, nous affichons en majuscules les lettres (bien placées) qui ont été découvertes jusque là (la première lettre étant donnée dès le départ), les lettres manquantes étant remplacées par un tiret. Puis après la saisie du mot, nous affichons en majuscule les lettres communes avec les mots à découvrir bien placées et en minuscule les lettres communes mal placées.

La partie : notre jeu offre la possibilité de jouer à un ou à deux . Après avoir sélectionner le nombre de joueur, la longueur du mot à deviner est demandé (entre 5 et 10 lettres). Puis dans le cas d’une partie à 2, le nombre de grilles de jeu sur lesquelles les adversaires souhaitent s’affronter est demandé. Dans le mode solo, chaque partie s’effectue sur une seule grille.

Les règles : dans la version 1 joueur pour qu’un essai soit validé, le mot proposé doit figurer dans le dictionnaire (et doit être bien orthographié), il doit commencer par la bonne lettre et doit être de la bonne longueur. Si le mot n’est pas valide, il est redemandé au joueur sans qu’il ne soit pénalisé par la perte d’un essai. Voici un exemple de partie :

Dans la version 2 joueurs, la main passe

  • dans chacun des cas précédents
  • au cas ou le mot n’est pas découvert au terme des 6 essais, auquel cas l’adversaire bénéficie d’une seule tentative pour découvrir le mot, mais conserve la main pour la grille suivante en cas d’échec.

Les fonctions

la fonction dico_n_lettres

def dico_n_lettres(dico):
#fonction qui crée une fois pour toute des dictionnaires
#de mots avec un nombre donné de lettres à partir d un
#fichier texte
   for n in range(1,25):
      path=os.getcwd()+'/'                   # définit le répertoire ou se trouve le ditionnaire
      dico1 = path+dico+".txt"               # fichier contenant le dictionnaire 
      dico2 = path+dico+str(n)+".txt"        # fichier qui contiendra le dictionnaire des mots à n lettres 
      fichier1 = open(dico1, "r")
      fichier2 = open(dico2, "w")
      for mot in fichier1:
          if len(mot) == n+1:                # n+1 car on doit tenir compte du caractère de retour à la ligne
              fichier2.write(mot)     
      fichier1.close()
      fichier2.close()

Nous avons récupéré sur le site https://www.lama.univsavoie.fr/pagesmembres/hyvernat/Enseignement/1415/info113/tp6.html deux dictionnaires sous la forme de fichiers .txt . Le premier contrairement au second contient les formes conjuguées des verbes et les pluriels des noms. La fonction précédente a pour but de créer une seule fois (ils sont installés sur le répertoire courant lors de la première exécution du programme), à partir du dictionnaire choisi, des dictionnaires constitués uniquement des mots de même longueur.

La fonction choisir_un_mot

def choisir_un_mot(dico,n):
#fonction qui va choisir aléatoirement un mot
#de n lettres
    path=os.getcwd()+'/'
    dico = path+dico+str(n)+".txt"
    fichier = open(dico, "r")
    liste_mots = fichier.readlines() # met tous les mots du fichiers dans une liste
    i = randint(1,len(liste_mots))
    mot = liste_mots[i]              # prend au hasard un mot dans la liste
    mot = mot.replace('\n','')       # supprime le caractère de retour à la ligne
    fichier.close()
    return(mot)

Cette fonction va utiliser le dictionnaire créé par la fonction précédente pour sélectionner aléatoirement un mot de n lettres qui servira de mot à deviner dans le jeu.

La fonction lettres_placées

def lettres_placees(liste1,liste2,liste3):
# fonction qui met dans liste1 les lettres 
# communes bien placées des liste2 et liste3
    liste = []
    liste0 = []
    for i in range(len(liste2)):
        if liste2[i]==liste3[i]:
            liste0.append(liste2[i])
        else:
            liste0.append('')
    for i in range(len(liste1)):
        if liste1[i]==liste0[i]:
            liste.append(liste1[i])
        else:
            liste.append(liste1[i]+liste0[i])
    return(liste)

Avec la fonction lettres_communes elles sont le cœur de notre programme. Cette fonction a pour but de mettre à jour la liste des lettres bien placées découvertes depuis le début de la partie. La variable liste1 contient la liste des lettres bien placées à mettre à jour et liste2 et liste3 les listes à comparer (le mot mystère et le dernier mot joué) et dont les lettres communes et bien placées vont être ajoutées à liste1.

La fonction lettres_communes

def lettres_communes(liste1,liste2):
# Retourne une liste avec toutes les lettres
# de la liste1 se trouvant dans la liste2
# les lettres bien placées sont en majuscule
# les autres sont en minuscule.
    liste = []
    liste3 = []
    for i in range(len(liste1)):
       liste.append('')
       liste3.append(liste2[i])
    for i in range(len(liste1)):
        if liste1[i]==liste3[i]:
            liste[i]=liste1[i].upper()
            liste3[i]=''
    for i in range(len(liste1)):
        for j in range(len(liste1)):
            if liste1[i]==liste3[j] and liste[i]=='':
                liste[i]=liste1[i].lower()
                liste3[j]=''
                break     
    return(liste)

Cette fonction est chargée de trouver les lettres communes entre liste1 et liste2, (qui représentent le mot joué et le mot à deviner) retournant ces lettres en majuscule pour les lettres bien placées et en minuscules pour les autres. Une des principales difficulté dans la conception de cette fonction a été la gestion des lettres dont le nombre d’apparition était différente dans les deux mots.

La fonction teste_mot

def teste_mot(liste,lettre,dico,n):
# Teste si le mot proposé par le joueur
# est valide : il doit commencer par 'lettre'
# se trouver dans dico et être de n lettres.
    test=True
    mot=''.join(liste).lower()   #transforme 'liste' en chaine de caractère en minuscule
    path=os.getcwd()+'/'
    dico = path+dico+str(n)+".txt"
    fichier = open(dico, "r")
    liste1 = fichier.readlines() # met tous les mots du dico dans une liste
    liste_mots=[]
    for mot1 in liste1:
        liste_mots.append(mot1.replace('\n',''))
    if  len(liste)!=n:                # teste si le mot est de la bonne longueur
       test=False
       print('Ce mot n est pas de la bonne longueur.')
    elif (mot not in liste_mots):     # teste si le mot est dans le dico
       test=False
       print('Ce mot n est pas dans le dictionnaire.')
    elif liste[0]!=lettre:            # teste si le mot commence par la bonne lettre
       test=False            
       print('Ce mot ne commence pas par la lettre '+lettre)
    fichier.close()
    return(test)

Cette fonction a pour but la validation (ou pas) de chaque mot entré par le joueur. Le mot est validé s’il commence par la bonne lettre, est constitué du bon nombre de lettres et se trouve dans le dictionnaire.

Les difficultés rencontrées

1. Pour la création et la gestion des dictionnaires nous nous sommes aidés du site https://python.sdv.univ-paris-diderot.fr/07_fichiers/ qui explique clairement les manipulations de base des fichiers (ouverture en mode lecture/écriture, fermeture, mise sous forme de liste de chaîne de caractères du contenu,…) et nous avons dû nous familiariser avec le module os pour indiquer le répertoire dans lequel se trouve les dictionnaires. Une des difficulté qui est apparue lors de la création des dictionnaires vient du fait que la longueur des mots ne correspondait pas à celle demandée (par exemple les mots de 5 lettres apparaissaient lorsqu’on en demandait 6. C’est après plusieurs tests que nous avons compris que le décalage venait du caractère ‘saut de ligne’ présent mais qui n’apparaissait pas quand on affichait les mots.

2. Pour la fonction « lettres_communes » la gestion des lettres dont le nombre d’apparition était différente entre les mots à comparer nous a aussi posé quelques problèmes. Pour y remédier, la solution que nous avons trouvé a été d’ « effacer » du mot à deviner une lettre commune une fois qu’elle a été trouvée (pour éviter de la recompter si elle apparaît une nouvelle fois dans le mot joué), en remplaçant la lettre en question par le caractère ‘ ‘. Alors que cette opération d’effacement s’effectuait en local (uniquement à l’intérieur de la fonction), la liste modifiée l’était également dans le programme principal. Pour régler le problème, nous avons décidé d’utiliser une liste intermédiaire, pour éviter de toucher à la liste passée en argument. Mais le résultat fut le même. Après quelques recherches sur internet, nous avons compris que le problème était inhérent aux listes et après plusieurs tentatives , nous sommes parvenus à régler le problème en passant par une liste auxiliaire créée non plus par une simple affectation mais en la remplissant grâce à une boucle et la commande .append().

3. Nous avons tenté de prendre en compte la gestion du temps, c’est-a-dire limiter à 10 s la durée de chaque essai mais la simple utilisation du module time ne donnait pas de résultat satisfaisant. En cherchant sur internet, nous avons vu qu’il était possible de créer un minuteur grâce au module threading mais après quelques essais cela s’est avéré plus compliqué que prévu et nous avons décidé de renoncer à cette fonctionnalité pour cette version mais nous espérons et envisageons de l’ajouter dans le futur.

Le fichier motus.py et les dictionnaires

Conclusion

Ce projet libre nous a permis de réaliser notre premier jeu en python. Après avoir longuement hésité, nous avons finalement opté pour MOTUS qui s’est finalement révélé très intéressant à programmer avec quelques challenges. Bien sûr, il reste encore beaucoup à accomplir pour se rapprocher du jeu original, notamment l’utilisation d’une interface graphique grâce au module tkinter ou encore la gestion du temps. Nous avions également pensé à intégrer des niveaux de difficulté en créant par exemple des dictionnaires adaptés (en associant à chaque mot un coefficient indiquant sa « difficulté » sur le même principe que le Scrabble). Toutes ces améliorations feront peut-être l’objet d’un futur projet.

Tutoriels

Comment utiliser les convertisseurs de fichiers en ligne ?

Vous voulez convertir un fichier pdf en fichier docx, un mp4 en mp3 ou encore d’autres types de fichiers ? Mais vous ne savez pas comment faire : ce tutoriel est fait pour vous. Vous retrouverez une sélection de convertisseurs, des astuces pour convertir au mieux vos fichiers, et sans oublier les risques et les menaces liés à ce procédé.

Les meilleurs sites pour convertir

Lorsque l’on recherche sur internet, on fait face à une multitude de liens vers différents convertisseurs; mais on ne sait souvent pas lesquels choisir.

Voici une liste de convertisseurs testés et approuvés avec chacun leurs particularités et leurs avantages.

  • Convertio est un des convertisseurs les plus connus et les plus utilisés (33 573 To de données converties). Il bénéficie d’un grand nombre de fichiers et d’une forte sécurité car il supprime votre fichier 24 heures après l’avoir converti. Autre avantage et pas des moindres, il est gratuit. Mais attention, le site limite le nombre de conversions à 10 par jour et n’accepte aucun fichier de plus de 100 Mo, ce qui limite la conversion de photos ou de vidéos de bonne qualité.
  • Free Online File Converter est un convertisseur similaire à Convertio car il est également gratuit et il dispose aussi d’un grand nombre de fichiers disponibles. Mais à l’inverse, il y a aucune limite journalière et la limite pour le poids du fichier est de 300 Mo. Cependant, ce site dispose de quelques défauts notamment son affichage « old school », ou son manque de clarté concernant la sécurité des documents.

  • Top-conv est un convertisseur payant (mais avec un bon rapport qualité/prix). Je le conseille si vous avez besoin d’un convertisseur puissant, rapide, sécurisé. C’est le meilleur notamment grâce à son offre à 50 centimes pour 48h qui permet de convertir de nombreux fichiers de poids important comme des images ou des vidéo avec de très bonnes qualités. Par contre, attention à bien arrêter l’abonnement à 50 centimes (au bout de 48h) afin d’éviter de payer la suite de l’abonnement qui est beaucoup plus onéreuse (28,20 euros par mois).

On fait comment ?

Pour notre exemple, on va partir d’un simple fichier bloc-notes pour qu’il devienne une photo ( format jpg).

  • Choisir le convertisseur le plus adapté à votre besoin. Dans cette exemple, on va prendre Convertio, mais on aurait très bien pu en prendre un autre.

  • Prendre le fichier que vous souhaitez convertir. ⚠️ Il faut respecter la taille maximale acceptée, sinon il y aura une erreur ( je n’aime pas les erreurs).
  • 2ème étape, il y aura un choix capital à faire, un choix déterminant… Il faudra décider du format dans lequel le document sera converti. Comme dit précédemment, le choix de formats de fichier est vaste. Un document texte peut devenir une photo (format jpg), un PDF, un gif…
  • Enfin attendez la fin de la conversion pour télécharger votre nouveau fichier. Youpi 👍

⚠️Je vous déconseille fortement de convertir un fichier plusieurs fois car cela pourrait altérer la qualité de votre document et modifier la mise en page, les photos ou encore les formes utilisées dans votre document.

Dangers ⛔

Ce procédé de conversion de fichier n’est pas sans risque, et peut vous provoquer plusieurs problèmes.

Premièrement, un site peut stocker sur des serveurs vos fichiers, je déconseille de convertir des documents sensibles. Aussi, ces fichiers peuvent fuiter car aucun site de conversion n’est à l’abri d’un piratage et votre fichier se retrouverait entre de mauvaises mains.

Certains sites peuvent donner des virus pouvant endommager votre ordinateur. C’est pourquoi je vous conseille d’utiliser principalement les 3 convertisseurs proposés au début de l’article. Dans le cas contraire si vous souhaitez utiliser d’autres convertisseurs, vérifier leur fiabilité sur les différents forums et utiliser un anti-virus pour une meilleur protection.

J’espère que cet article vous a aidé et que vous êtes devenu des pros😎 de la conversion de fichiers.

Art

Balles et ballons : les ballons du système solaire

Le premier projet de la classe de 1ère NSI est « Regard de géomètre ». Ce projet consiste en la création d’une image basée sur un ou plusieurs thèmes donnés. Pour notre image, on a choisi les thèmes astronomie et balles et ballons. Nous avons voulu représenter le système solaire mais en remplaçant les planètes et le Soleil par des balles et des ballons de différents sports.

Les étapes de création de notre image

Après avoir choisi nos thèmes et décidé de l’illustration que l’on souhaitait faire, nous avons commencé par le fond de notre illustration. Pour cela, on voulait un fond noir avec des étoiles représentées par des points blancs et de tailles différentes placées aléatoirement sur l’image. Cependant, les grosses étoiles à cause de leur couleur blanche, se voyaient trop par rapport aux plus petites. On a alors ajouté une couleur un peu plus grise pour les grosses étoiles mais on a gardé le blanc pour les petites. Pour faire cela, nous avons utilisé une instruction conditionnelle :

import turtle
import random
turtle.speed(0)
for i in range(150):
    turtle.penup()
  turtle.goto(random.randint(-640,640),random.randint(-350,350)) 
    turtle.pencolor("black")
    turtle.pendown()
    a=random.randint(1,5)
    if a<2:
        turtle.begin_fill()
        turtle.fillcolor("white")
        turtle.circle(a)
        turtle.end_fill()
    else:
        turtle.begin_fill()
        turtle.fillcolor("#e1e1df")
        turtle.circle(a)
        turtle.end_fill()

Ce qui donne avec le fond:

Tracé du ciel étoilé

Dans un second temps, nous avons choisi les balles que l’on voulait représenter puis nous les avons tracées chacune séparément pour avoir le rendu le plus fidèle possible. Les balles choisies sont:

  • la balle de tennis
  • le ballon de basket-ball
  • le ballon de rugby
  • la balle de base-ball

A l’origine, on voulait faire le ballon de football plutôt que la balle de base-ball mais le motif de ce ballon est un peu trop complexe à faire et n’apportait que peu d’intérêt pour notre script.

Script pour le tracé du ballon de basket :

import turtle
turtle.bgcolor("black")
turtle.begin_fill()
turtle.fillcolor("coral")
turtle.goto(0,-3)
turtle.circle(98)
turtle.end_fill()
turtle.penup()
turtle.goto(-97,93)
turtle.left(-73)
turtle.pendown()
turtle.pensize(5)
turtle.pencolor("black")
turtle.circle(100,150)
turtle.penup()
turtle.goto(-97,93)
turtle.left(180)
turtle.pendown()
turtle.circle(100,-150)
turtle.penup()
turtle.goto(-97,93)
turtle.right(107)
turtle.pendown()
turtle.forward(186)

Tracé du ballon de basket

Dans la dernière étape de la création de notre image, nous avons regroupé toutes nos créations (fond, balles et ballons) dans un même script et nous avons rajouté certaines fonctionnalités comme les ellipses ou l’effet d’ombre qui vous seront montrés plus loin. Mais, lors de ce regroupement, nous avons fait face à plusieurs problèmes notamment au positionnement des balles et également à leur proportion (un ballon de basket ne peut pas être plus petit qu’une balle de tennis). Pour cela, on a effectué une suite d’essai-erreur jusqu’à ce que le résultat nous plaise.

Rendu final

Les fonctions utilisées dans le script

La première fonction importante de ce script est la fonction « orbite ». Elle consiste en la création d’une « fausse ellipse » à l’aide de 4 arcs de cercles de rayons différents. Cette fonction est plutôt simple mais extrêmement efficace.

def orbite(rayon):
  turtle.seth(-45) 
  for i in range(2):
      turtle.circle(rayon,90)
      turtle.circle(rayon/2,90)
  return()

La deuxième fonction marquante de ce script est la fonction permettant de créer un effet d’ombre sur les balles et ballons ayant une forme circulaire. Pour cela, il faut créer un dégradé de couleur formé à l’aide de cercles de plus en plus petits dont la couleur varie en même temps que le rayon diminue. Cette fonction s’appelle « surface ».

def surface(couleur,rayon,posx,posy):
    r=couleur[0]
    g=couleur[1]
    b=couleur[2]
    turtle.pensize(5)
    for i in range(51):
        turtle.home()
        turtle.goto(posx,posy)
        turtle.pendown()
        if ((r-i*1.5)>=0) and ((g-i*1.5)>=0) and ((b-i*1.5)>=0):
            r1=r-i*1.5; g1=g-i*1.5; b1=b-i*1.5;
        elif ((r-i*1.5)<0): r1=r
        elif ((g-i*1.5)<0): g1=g
        else: b1=b
        turtle.pencolor((r1/255,g1/255,b1/255))
        turtle.circle((100-2*i)*rayon)
        turtle.penup()

Enfin, la dernière fonction est la fonction étoile, elle permet comme son nom l’indique de tracer des étoiles de taille et avec un nombre de branches variables. Elle a pour paramètres le nombre de branches et la longueur des branches.

def etoiles(branches, longueur):
    turtle.begin_fill()
    turtle.fillcolor("white")
    for i in range(branches):
        turtle.forward(longueur)
        turtle.right(180+180/branches)
        turtle.forward(longueur)
        turtle.left(180-180/branches)
    turtle.end_fill()

Malheureusement, cette fonction a un défaut que l’on n’a pas su régler. Lorsque l’on choisit un nombre pair de branches, le nombre n’est pas respecté.

Exemple: lorsque l’on exécute etoiles(6,100). Le nombre de branches n’est pas correct.

Alors que lorsqu’on veut faire une étoile avec un nombre de branches impair, le nombre de branches est respecté.

Exemple: lorsque l’on exécute etoiles(9,100). Le nombre de branches est correct.

Problèmes rencontrés

Lors de la création de notre script, nous avons rencontré plusieurs problèmes comme le positionnement des balles ou encore la proportion des ballons mais également des problèmes qui survenaient lorsqu’on voulait créer une image. Ce problème venait de la commande bgcolor(). Cette fonction consiste à colorier le fond de la toile par la couleur de son choix. Cependant, sur le script nous permettant de créer nos images, le fond n’apparaissait pas. Pour résoudre ce problème, nous avons rajouté au script une boucle faisant des allers-retours sur la toile à l’aide d’un stylo épais permettant de créer manuellement ce fond.

turtle.goto(-760,400)
turtle.pensize(10)
turtle.right(90)
for i in range(75):
    turtle.forward(420*2)
    turtle.left(90)
    turtle.forward(10)
    turtle.left(90)
    turtle.forward(420*2)
    turtle.right(90)
    turtle.forward(10)
    turtle.right(90)

Conclusion sur notre premier projet en NSI

Ce premier projet nous a permis d’approfondir nos connaissances en turtle et de créer notre premier « gros script » de cette année en python en faisant appel à toutes les fonctions vues en cours. Nous aurions pu essayer d’apporter des améliorations avec un peu plus de temps en ajoutant par exemple d’autres balles plus complexes comme la balle de golf.

Télécharger le .py

L’image finale