Vous pouvez me contacter via Facebook pour questions & suggestions : Page Facebook relative à mon site
Dans ce chapitre nous abordons des programmes un peu
plus complexes : des jeux et des programmes de cryptage.
Ce sera aussi l'occasion de présenter de nouveaux modules Python.
Thème : tirage au sort de cartes dans un jeu de 32 cartes.
Le code à saisir :
# nom programme : tirage_carte.py from random import * enseignes = ['pique', 'coeur', 'carreau', 'trèfle'] rang = ['A', 'R', 'D', 'V', 10, 9, 8 , 7] reponse = "O" while reponse not in "nN": carte_e = choice (enseignes) carte_r = choice (rang) print('carte tirée : ' , carte_r ,' de ' , carte_e) reponse = input("continuez ? O/N : " )
Étudions le code maintenant.
Ce programme est construit à partir de deux listes. La première liste comprend 4 éléments (les 4 enseignes ou "couleurs")
et la seconde comprend 8 éléments. On utilise donc un jeu de 32 cartes.
Si on voulait utiliser un jeu de 52 cartes il suffirait de modifier l'une des listes.
Notez que la deuxième liste est ce que j'appelle " liste mixte" avec des chaines et des nombres.
Observez bien le test qui permet de sortir de la boucle while. En effet l'utilisateur qui veut arrêter le tirage doit taper "n" ou "N".
S'il tape autre chose il reste dans la boucle.
La fonction choice(liste) :
Cette fonction permet d'extraire de façon aléatoire un élément d'une liste.
Cette fonction ne fait pas partie des fonctions "natives" mais du module "random" qu'il faut donc importer.
Ça serait bien qu'après 5 pioches du joueur, on puisse visualiser sa main.
# nom programme : tirage_carte_bis.py from random import * enseignes = ['pique', 'coeur', 'carreau', 'trèfle'] rang = ['A', 'R', 'D', 'V', 10, 9, 8 , 7] # jeu stocke dans une liste mon_jeu_liste=[] #liste vide for i in range(5): carte_e = choice (enseignes) carte_r = choice (rang) #print('carte tirée : ' , carte_r ,' de ' , carte_e) carte_tiree = str(carte_r) + " de " + carte_e mon_jeu_liste.append(carte_tiree) print("mon jeu : ") for carte in mon_jeu_liste : print(carte, end=" - ")
Comme le nombre de pioches est connu (5), il faut mieux utiliser la structure "for ... " que la structure "while ...".
À chaque passage dans la boucle il y a tirage au sort d'une carte.
Le nom de la carte tirée devient un nouvel élément de la liste "mon_jeu_liste" grâce à la méthode append().
Notez le paramètrage de la fonction print() dans la deuxième boucle. L'argument end = " - " interdit le saut de ligne
qui survient normalement après un "print()".
mon jeu : V de pique - V de carreau - V de pique - 10 de carreau - 10 de carreau -
Problème : deux fois le valet de pique et deux fois le 10 de carreau.
Voir le chapitre 8 dans ce même tuto pour une version debuggée grâce à l'emploi d'une structure de données appelée "ensemble".
Pendant la guerre, les nazis disposaient d'une machine de cryptage appelé ENIGMA.
La clé de cryptage changeait chaque jour.
Les Britanniques, à l'initiative du chercheur Alan Turing, réalisèrent un super calculateur électro-mécanique surnommé
la "bombe" pour casser le code avec un certain succès.
Ci-dessous à gauche la fameuse "bombe" et à droite la machine enigma.
En informatique chaque lettre, symbole a un code ASCII. Les logiciels manipulent en fait les codes ASCII des symboles et lettres.
Les codes 0 à 31 ne codent pas des caractères mais des symboles.
Les codes 65 à 90 représentent les majuscules. Les codes 97 à 122 représentent les minuscules.
La fonction ord(C) renvoie le code ASCII de la lettre C majuscule.
La fonction chr(n) renvoie la lettre ou symbole associé au code ASCII n.
# du code ASCII à la lettre correspondante for i in range(65,123): print("code ASCII: ", i, "lettre : " , chr(i))
code ASCII : 65 lettre correspondante : A code ASCII : 66 lettre correspondante : B code ASCII : 67 lettre correspondante : C code ASCII : 68 lettre correspondante : D code ASCII : 69 lettre correspondante : E code ASCII : 70 lettre correspondante : F ...
# nom programme code_ascii_ter.py #affiche pour chaque lettre majuscule de l'alphabet latin # de son code ASCII majuscules = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" for lettre in majuscules : code =ord(lettre) print(lettre, " a pour code ascii : " , code)
Au travers de ce programme je vous montre que l'on peut parcourir une chaine de la même façon qu'une liste ;
avec une boucle for ... in nomChaine
Je rappelle que le nom de la variable après "for" est libre.
A a pour code ascii : 65 B a pour code ascii : 66 C a pour code ascii : 67 D a pour code ascii : 68 E a pour code ascii : 69 F a pour code ascii : 70 ...
Je vous propose maintenant quelques programmes de cryptage.
Imaginons un cryptage qui consiste à remplacer chaque caractère par son code ASCII.
#cryptage d'un message basé sur le code ASCII #nom programme : cryptage_ascii.py message_clair =input("tapez un message à crypter : ") message_crypte ="" #chaine vide longueur = len(message_clair) for lettre in message_clair : codage = str(ord(lettre)) message_crypte += codage print ("message crypté à envoyer :", message_crypte)
Là encore je vous montre que l'on peut parcourir une chaine avec la structure "for ... in nomChaine".
message_crypte += codage : emploi d'un opérateur d'affectation composé.
À chaque itération on rajoute un code ASCII à la variable message_crypte
tapez un message à crypter : attaque de la colline 17 à 6 heures message crypté à envoyer : 971161169711311710132100101321089732991111081081051 1010132495532224325 432104101117114101115
Il faudrait maintenant imaginer le programme de décryptage OU à défaut une table de décryptage ...
Grâce à cette table le destinaire du message pourra le décrypter rapidement.
#nom programme : table_substitution.py # production table qui permet de traduire un message crypté en ascii alphabet ="abcdefghijklmopqrstuvwxyz 0123456789" longueur = len(alphabet) print('nombre de caractères :' , longueur) table ="" # chaine vide print ("table de substitution :") for caract in alphabet : code = ord(caract) cle = str(code) + " = " + caract +" ; " #clé de décryptage table += cle # ajout dans table print (table)
nombre de caractères : 36 table de substitution : 97 = a ; 98 = b ; 99 = c ; 100 = d ; 101 = e ; 102 = f ; 103 = g ; 104 = h ; 105 = i ; 106 = j ; 107 = k ; 108 = l ; 109 = m ; 111 = o ; 112 = p ; 113 = q ; 114 = r ; 115 = s ; 116 = t ; 117 = u ; 118 = v ; 119 = w ; 120 = x ; 121 = y ; 122 = z ; 32 = ; 48 = 0 ; 49 = 1 ; 50 = 2 ; 51 = 3 ; 52 = 4 ; 53 = 5 ; 54 = 6 ; 55 = 7 ; 56 = 8 ; 57 = 9 ;
Vous devez décrypter ce message reçu par chaque chef d'unité en utilisant la table de conversion.
99101115115101122321081013210210111732973249493297
109321081013249493210011
732109111105115324949
Le cryptage de chaque caractère par son code ASCII est relativement simple à réaliser mais en contrepartie il est aussi très facile
à "casser".
Nous allons maintenant aborder une autre technique dite "leet speak".
Le principe est d'utiliser des caractères graphiquement voisins des caractères usuels, par exemple "5" au lieu de "S",
"7" au lieu de "T" ,etc.
#nom programme cryptage_leet_speak.py message_clair =input("Tapez le message en clair : ") message_code = message_clair.replace('s','5') message_code1 = message_code.replace('t','7') message_code2 =message_code1.replace('g','9') message_code3 =message_code2.replace('h','4') message_code4 =message_code3.replace('i', '1') message_code5 = message_code4.replace('u','||') message_code6 =message_code5.replace('e','!') print("message à envoyer : " , message_code6)
Tapez le message en clair : tout ce qui se concoit bien s enonce clairement message à envoyer : 7o||7 c! q||1 5! conco17 b1!n 5 !nonc! cla1r!m!n7
Ce programme est basé sur la méthode replace() que l'on peut appliquer à une chaine de caractères.
Remarque : lettre "u" remplacée par "||" (double pype) et "e" par " !" (point d'exclamation)
Ce programme "marche" mais sur un plan algorithmique, il est nul ! Il a été écrit rapidement.
Or en programmation il ne faut confondre vitesse et précipitation.
Ce programme est mauvais car d'abord il est trop long et sa maintenance est difficile. Il y a trop de variables utilisées :
message_code, ... message_code6.
Cette version améliorée repose sur l'utilisation d'une liste de listes.
#nom programme : cryptage_leek_speak_plus.py message_clair = input("tapez le message en clair : ") message_code = message_clair cle = [ ['s','5'], ['t','7'], ['g', '9'], ['h', '4'], ['u','||'], ['e','!'] ] for ele in cle: clair =ele[0] code = ele[1] message_code = message_code.replace(clair, code) print('message codé : ' , message_code)
On parcourt la liste de listes.
à chaque itération on lit un élément de la liste principale donc une sous-liste.
Ainsi à la première itération on récupère 's' dans clair et '5' dans code.
Püis on remplace dans la chaine messge_code les 's' par '5'.
Tapez le message à crypter : "sans methode la pensee erre l action tatonne"
message codé : 5an5 m!74od! la p!n5!! !rr! l ac7ion 7a7onn!
Il serait souhaitable que toutes les voyelles soient cryptées.
Le codage dit de "César" est une technique de cryptage utilisée dès l'antiquité. Le principe est simple : décaler les lettres
de l'alphabet de une ou plusieurs positions. Par exemple en décalant vers la droite de 2 positions : a devient c, b devient d, ...
y devient a et z devient b.
Le principe est donc simple. Selon un calendrier, connu seulement de l'émetteur et du destinataire, la clé de cryptage peut changer :
par exemple, décalage droite de 2 puis la semaine suivante décalage droite de 4, etc.
# nom du programme : cryptage_cesar.py alphabet_clair ="abcdefghijklmnopqrstuvwxyz" alphabet_crypte =alphabet_clair[2:] + alphabet_clair[:2] print("alphabet clair : ", alphabet_clair) print("alphabet crypté équivalent : " , alphabet_crypte) alphabet_clair += " " alphabet_crypte += " " message_code ="" message_clair = input("tapez le message en clair : ") for lettre in message_clair : position = alphabet_clair.index(lettre) code = alphabet_crypte[position] message_code += code print('message crypté : ' , message_code)
alphabet_crypte =alphabet_clair[2:] + alphabet_clair[:2] : pratique du "slicing" pour produire l'alphabet crypté
Donc pour construire alphabet_crypte on extrait de alphabet_clair de l'indice à la fin puis on rajoute du
début jusqu'à l'indice 2 exclu.
On rajoute dans les deux alphabets le caractère " " en fin de chaine. Donc " " sera crypté en " " !
alphabet clair : abcdefghijklmnopqrstuvwxyz alphabet crypté équivalent : cdefghijklmnopqrstuvwxyzab tapez le message en clair : ce qui vont mourir te saluent message crypté : eg swk xqpv oqwtkt vg ucnwgpv
L'utilisateur doit saisir la règle de décalage : 2 ou 3 ou 4 ou 5. Le programme s'occupe du reste.
Le rendu, si vous saisissez 3 de décalage :
tapez le décalage 2/3/4 : 3 tapez le message en clair : ave cesar message crypté : dyh fhvdu
Prévoyez un contrôle de saisie dans d (d comme "décalage") doit être un élément de la liste [2,3,4].
Astuce programmatique : placer l'instruction input() dans une boucle while.
... d = 1 while d not in [2,3,4]: d =input("tapez le décalage 2/3/4 : ") d =int(d) # la saisie avec input est toujours de type str donc conversion obligatoire ..