Afficher avec Python

Identification

Infoforall

2 - Expressions numériques


Cette activité vous présente une première utilisation de Python de façon à effectuer quelques calculs.

Nous allons voir que l'interpréteur Python évalue les ordres qu'on lui transmet en respectant des règles précises.

Nous répondrons notamment à ce problème : comment parvenir à trouver que la case 9 est sur la colonne 1 et la ligne 2 ?

Logiciel nécessaire pour l'activité : Python 3 : Thonny, IDLE ou un site sur lequel on peut faire interpréter du Python

Evaluation : 8 questions

 questions 04-07-11-12-15-16-19

 questions 20

Exercices supplémentaires 🏠 : oui

Documents de cours PDF : .PDF

Sources latex : .TEX, entete.tex et licence.tex

Résumé : Version HTML ou imprimable ou ou PDF (couleur ou gris)

1 - Expression comportant un opérateur

1.1 Expression - Valeur - Opérateur

Une expression caractérise une séquence de valeurs associées à des opérateurs.

L'interpréteur Python évalue l'expression et fournit sa valeur associée. Cette action se nomme une évaluation.

Cas simple :

>>> 4 + 5 9
  • 4 et 5 sont des valeurs.
  • + est un opérateur.
  • 4 + 5 est une expression.
  • 9 est la valeur de l'évaluation.

Les opérations arithmétiques classiques sont représentées de cette façon en Python :

  • + symbolise l'addition
  • - symbolise la soustraction
  • * symbolise la multiplication
  • / symbolise la division
  • ** symbolise la puissance
1.2 DEFINITION : Priorité d'évaluation

L'évaluation d'une expression est séquentielle et progressive  : l'interpréteur Python effectue certaines opérations en priorité.

Voici les règles de priorité que respecte l'interpréteur :

  1. les parenthèses d'abord
  2. ensuite, l'opérateur de puissance **
  3. puis, les opérateurs * /
  4. enfin, les opérateurs + -
  5. En cas d'égalité de priorité : le plus à gauche d'abord.

Exemple

10 + (5 + 3) * 2

10 + 8 * 2

10 + 16

26

Pour vérifier, il suffit de demander poliment à Python de faire le calcul :

>>> 10 + (5 + 3) * 2 26

Exemple 2

5 + 10 / 2 * 3

5 + 5.0 * 3

5 + 15.0

20.0

1.3 Quotient et reste d'une division euclidienne avec // et %

On désigne parfois ces divisions euclidiennes sous le terme de "divisions entières".

A - Rappels sur les divisions euclidiennes

Il s'agit de diviser un nombre a par un nombre b, en trouvant :

  • Le quotient, c'est à dire le nombre de paquets égaux qu'on peut faire en divisant a par b.
  • Le reste, c'est à dire le nombre d'éléments restants après création des paquets.
  • Exemple avec la division euclidienne de 10 par 5 :
  •      10 │ 5
            ├────
    reste 02
    

    Le quotient vaut 2 et le reste vaut 0.

    On remarquera qu'on peut également le justifier en écrivant 10 = 2*5 + 0

B - Opérateur Python //

En Python, la syntaxe permettant d'obtenir le quotient de la division entière de 10 par 5 est 10 // 5.

Cela revient à demander à Python "Python, quel est le quotient de la division euclidienne de 10 par 5 ?"

Moins formellement, "Python, combien de paquets de 5 objets peut-on faire avec 10 objets ?"

>>> 10 // 5 2
C - Opérateur Python %

En Python, la syntaxe permettant d'obtenir le reste de la division entière de 10 par 5 est 10 % 5.

Cela revient à demander à Python "Python, quel est le reste de la division euclidienne de 10 par 5 ?"

Moins formellement, "Python, combien va-t-il me rester d'objets en faisant des paquets de 5 objets ?"

>>> 10 % 5 0
D - Quelques autres exemples
  1. Division entière de 11 par 5
  2. Voici la division posée :

         11 │ 5
            ├────
    reste 12
    

    On peut également le justifier en écrivant 11 = 2*5 + 1

    Et voici pour Python :

    >>> 11 // 5 2 >>> 11 % 5 1
  3. Division entière de 13 par 5
  4. Voici la division posée :

         13 │ 5
            ├────
    reste 32
    

    On peut également le justifier en écrivant 13 = 2*5 + 3

    Et voici pour Python :

    >>> 13 // 5 2 >>> 13 % 5 3
  5. Division entière de 14 par 3
  6. Voici la division posée :

         14 │ 3
            ├────
    reste 24
    

    On peut également le justifier en écrivant 14 = 4*3 + 2

    Et voici pour Python :

    >>> 14 // 3 4 >>> 14 % 3 2
E - Priorité

L'opérateur // et l'opérateur % possèdent la même priorité que la multiplication ou la division.

Lorsque les deux sont présents, c'est donc l'ordre d'apparition qui tient lui de priorité. Attention, ils ne sont pas interchangeables.

>>> 1407 % 5 // 2 1 >>> 1407 // 2 % 5 3

Pourquoi ? Voici la décomposition des deux évaluations précédentes.

Déroulé de la première évaluation : 1407 % 5 // 2

1407 % 5 // 2

2 // 2

1

Déroulé de la première évaluation : 1407 // 2 % 5

1407 // 2 % 5

703 % 5

3

Vous avez vu plusieurs lignes de calcul possédant des espacements. Ceux-ci ne sont pas positionnés au hasard :

Ecrire un code clair 1 : les espaces dans les expressions

Lorsqu'une expression ne contient que des opérateurs ayant la même priorité, on laisse un espace entre les différentes termes :

Expressions correctement écrites : >>> 25 % 10 >>> 25 + 10 - 5 Expressions posant des problèmes de lecture : >>> 25%10 >>> 25+10+5

Lorsqu'une expression ne contient que des opérateurs ayant des priorités différentes, on ne place pas d'espace sur les opérateurs prioritaires :

Expressions correctement écrites : >>> 10 + 25*5 >>> 25/10 - 5 Expressions posant des problèmes de lecture : >>> 10+25*5 >>> 10 + 25 * 5 >>> 25/10-5 >>> 25 / 10 - 5

S'il faut des parenthèses, on ne rajoute pas d'espace au début ou à la fin de l'expression située dans les parenthèses.

L'expression dans la parenthèse est prioritaire sur la multiplication. Cette fois, on ne placera donc pas d'espace entre le + mais on en place autour du * :

Expressions correctement écrites : >>>(25 + 5) * 5 >>> (4 + 5) * (12 + 55) Expressions posant des problèmes de lecture : >>> (25+5)*5 >>> ( 25 + 5 ) * 5 >>> ( 25+5 ) * 5

Et pour les cas plus complexes ? On fait appel à son bon sens !

Les question sans icone particulière :

C'est une question "normale". Que faire ?

  • Vous tentez de faire la question
  • Si vous bloquez (trop longtemps), vous regardez la réponse en cliquant dessus.
  • Correction ?

    ...CORRECTION...

    Si ce n'est toujours pas clair malgré la réponse, vous m'appelez.

01° Tapez ceci dans la console interactive.

>>> 5 * 10 ??? >>> 15 - 4 ???

Questions :

  • Quelle est la valeur produite par la première expression ?
  • Quelle est la valeur produite par la deuxième expression ?
  • Quel est le symbole de l'opérateur de la deuxième expression ? Quel est son sens (son signification, sa sémantique) ?

...CORRECTION 1-2...

  • Quelles sont les valeurs de la première expression ?
  • Les valeurs de la première expression sont 5 et 10

  • Que donne l'évaluation de la deuxième expression ?
  • "Evaluer" veut dire fournir la valeur attribuée à l'expression. Ici 15-4 donne simplement 9

  • Quel est le symbole de l'opérateur de la deuxième expression ? Quel est son sens ?
  • Le seul opérateur de la deuxième expression est - dont le sens est la soustraction.

02° Donner, de tête, la valeur que va fournir Python en évaluant ces expressions. Vérifier ensuite en évaluant dans la console.

>>> 9*9 + 2 ? >>> 2 + 9*9 ? >>> 12 - 2*0.2 ? >>> 3*0.1 + 12 ?

...CORRECTION 1-2...

Pour comprendre ce calcul, il faut se souvenir que l'opérateur multiplication * est prioritaire sur l'opérateur addition +.

L'ordinateur va ainsi évaluer votre calcul progressivement, étape par étape :

>>> 9*9 + 2 >>> (9*9) + 2 >>> 81 + 2 83

Ca ne change rien pour le second du coup, les priorités sont les mêmes :

>>> 2 + 9*9 >>> 2 + (9*9) >>> 2 + 81 83

...CORRECTION 3-4...

Même principe : l'opérateur multiplication * est prioritaire sur l'opérateur soustraction -.

L'ordinateur va ainsi évaluer votre calcul progressivement, étape par étape :

>>> 12 - 2*0.2 >>> 12 - (2*0.2) >>> 12 - 0.4 11.6

Ca ne change rien pour le second du coup, les priorités sont les mêmes :

>>> 3*0.1 + 12 >>> (3*0.1) + 12 >>> 0.3 + 12 12.3

03° Evaluer de tête ces deux expressions. Donnent-elles le même résultat ?

>>> 3 + 2*3 + 2 ? >>> (3+2) * (3+2) ?

...CORRECTION...

L'ordinateur évalue ainsi la première expression :

>>> 3 + 2*3 + 2 >>> 3 + (2*3) + 2 >>> 3 + 6 + 2 >>> (3 + 6) + 2 >>> 9 + 2 11

Pour la deuxième expression, on respecte juste les parenthèses :

>>> (3+2) * (3+2) >>> 5 * (3+2) >>> 5 * 5 25

Les question avec l'icône stylo ✎ 

Ces questions seront notées si vous êtes sélectionné. Il faut donc mettre votre réponse sur votre copie.

✎ 04° Expliquer clairement les réponses fournies par Python sur ces calculs. Vérifier votre réponse en tapant l'expression dans la console.

>>> 12 // 5 ? >>> 12 % 5 ? >>> 12 // 9 ? >>> 12 % 9 ? >>> 7 // 2 ? >>> 7 % 2 ? >>> 380 % 360 ?

05° Vous voulez acheter des paquets de gâteaux. Un paquet coûte 12 euros. Vous avez 100 euros sur vous :

  1. Ecrire le calcul à demander à l'interpréteur pour savoir combien de paquets vous pouvez acheter avec 100 euros.
  2. Ecrire le calcul à demander à l'interpréteur pour savoir combien d'euros il va vous rester après cet achat.

...Correction...

On trouve le résultat avec deux lignes.

"Python, combien de paquets puis-je acheté ?"

>>> 100 // 12 8

"Python, combien va-il me rester ?"

>>> 100 % 12 4

On peut donc acheter 8 paquets et il nous restera 4 euros.

Cela revient à dire que 100 = 8*12 + 4.

06° Taper les expressions suivantes qui illustrent l'opérateur ** : la puissance.

>>> 3**2 9 >>> 4**2 16 >>> 5**2 25 >>> 10**2 100 >>> 10**3 1000

Question :

Comment peut-on écrire 10**6 uniquement en utilisant des multiplications ?

...Correction...

10**6 = 10 * 10 * 10 * 10 * 10 * 10

✎ 07° Noter sur votre copie les résultats des puissances de 2 successives suivantes :

>>> 2**2 ? >>> 2**3 ? >>> 2**4 ? >>> 2**5 ? >>> 2**6 ? >>> 2**7 ?

Question supplémentaire :

Proposer une autre façon de calculer 27 qui n'utilise que des multiplications.

08° On considère l'expression suivante : 5**2*5**2.

Question

  1. Réaliser sur papier l'évaluation de cette expression en expliquant clairement les étapes successives.
  2. Vérifier votre résultat sur la console Python.
  3. Ecrire l'expression de façon plus claire en utilisant des espaces de façon pertinente.

...correction...

>>> 5**2*5**2 >>> (5**2)*(5**2) >>> 25*25 625

La puissance étant prioritaire, nous aurions dû écrire l'expression sous cette forme plus claire :

>>> 5**2 * 5**2

On notera bien que 2**5 veut dire 25, ce qui correspond à 2*2*2*2*2 et pas 2*5.

De la même façon,

  • 10**1 veut dire 101, ce qui correspond à 10
  • 10**2 veut dire 102, ce qui correspond à 10*10
  • 10**3 veut dire 103, ce qui correspond à 10*10*10
  • 10**4 veut dire 104, ce qui correspond à 10*10*10*10

2 - Application à la résolution de problèmes

A quoi peut bien servir ce que nous venons de voir aujourd'hui, notamment la division euclidienne et le modulo ?

La programmation consiste en partie à faire une traduction : comment faire comprendre à l'interpréteur Python ce qu'on veut faire en utilisant uniquement les quelques mots qu'il utilise.

2.1 - Détection de décennie

Imaginons un ensemble de taxis identifiés par un nombre entre 0000 et 9999. Un témoin sait qu'un suspect à prend un taxi dont la dizaine est 4. Comment identifier informatiquement tous les taxis dont le chiffre de la dizaine vaut 4 ? Il faudra savoir comment poser la question suivante à l'interpréteur Python : "Quel est le chiffre de la dizaine du taxi ?"

Imaginons par exemple que vous vouliez trouver le chiffre de la dizaine dans 2004. C'est 0 bien entendu. Ok. Mais comment demander à Python de nous répondre 0 sur ce cas ?

Il n'existe pas d'opérateurs basiques pour faire cela... Il va falloir composer avec ce qu'on sait demander à Python pour l'instant : + - * / // % **...

2.1 - Extraire le chiffre de l'unité, de la dizaine et de la centaine

Description du problème
  • Entrée du problème : un nombre ENTIER M positif
  • Exemple d'entrée : M =  1234 

  • Sortie du problème : un ensemble de chiffres représentant
    • le chiffre de l'unité u (avec l'exemple u =  4 ),
    • le chiffre de la dizaine d (avec l'exemple d =  3 ),
    • le chiffre de la centaine c (avec l'exemple c =  2 ),
Nombre M = 1 2 3 4
La case code 1000 100 10 1
On obtient donc 1000 200 30 4
Chiffre de l'unité

Il suffit de faire une division euclidienne par 10 et de récupérer le reste.

Exemples :

>>> 1234 % 10 4 >>> 489 % 10 9
Chiffre des dizaines

Il suffit de diviser le nombre par 10. Le chiffre de la dizaine se retrouve alors à la position de l'unité.

Pour récupérer ce chiffre, il suffit donc de faire une deuxième division euclidienne par 10 et de récupérer le reste.

Exemples :

# En deux étapes >>> 1234 // 10 123 >>> 123 % 10 3 # En une étape >>> 1234 // 10 % 10 3
Chiffre des centaines

Il suffit de diviser le nombre par 100. Le chiffre de la centaine se retrouve alors à la position de l'unité.

Il suffit de faire une deuxième division euclidienne par 10 et de récupérer le reste.

Exemples :

# En deux étapes >>> 1234 // 100 12 >>> 12 % 10 2 # En une étape >>> 1234 // 100 % 10 2

09° Expliquer clairement ce qu'on doit taper lors de la déclaration de la variable dizaine pour récupérer la dizaine de l'année stockée dans la variable a (quelque soit le contenu de a).

Exemple

>>> a = 2018 >>> dizaine = a... (à compléter) >>> dizaine 1

...CORRECTION 1-2...

>>> a = 2018 >>> dizaine = a // 10 % 10 >>> dizaine 1

10° Expliquer clairement ce qu'on doit taper lors de la déclaration de la variable centaine pour récupérer la centaine de l'année stockée dans la variable a (quelque soit le contenu de a).

Exemple

>>> a = 2018 >>> centaine = a... (à compléter) >>> centaine 0

...CORRECTION 1-2...

>>> a = 2018 >>> centaine = a // 100 % 10 >>> centaine 0

✎ 11° Expliquer clairement ce qu'on doit taper dans la console pour récupérer

  1. le chiffre des centaines d'une année contenu dans une variable b.
  2. le chiffre des milliers contenu dans une variable year.

✎ 12° Compléter la fonction siecle() qui reçoit une année (positive) dans son paramètre annee et qui renvoie le siècle de cette année.

1 2 3 4
def siecle(annee): """Renvoie le siècle de l'année reçue (entre 0 et 9999)""" return 0

Exemple d'appel :

>>> siecle(1983) 20 >>> siecle(2023) 21 >>> siecle(23) 1

(OPTION) : et si vous gériez les années négatives ?

2.2 Position d'une case sur un plateau

2.2 - Position d'une case sur un plateau de jeu

2.2.A - Description du plateau

Imaginons qu'on dispose d'un plateau de jeu de 4 cases sur 4 cases. Les cases sont numérotées de 0 à 15, comme indiqué ci-dessous :

La ligne du haut porte le numéro 0, la ligne du dessous le numéro 1...

La colonne de gauche porte le numéro 0 puis les autres 1, 2 et 3.

2.2.B - Numéro de ligne

Comment trouver le numéro de ligne d'une case dont on connaît le numéro ?

Il y a 4 cases par ligne et les cases commencent à 0.

Il suffit de récupérer le quotient de la division euclidienne du numéro de la case par 4.

>>> 3 // 4 0 >>> 4 // 4 1 >>> 7 // 4 1 >>> 8 // 4 2
2.2.C - Numéro de colonne

Comment trouver le numéro de colonne d'une case dont on connaît le numéro ?

Il y a 4 cases par ligne et les cases commencent à 0.

Il suffit de récupérer le reste de la division euclidienne du numéro de la case par 4.

>>> 3 % 4 3 >>> 4 % 4 0 >>> 7 % 4 3 >>> 8 % 4 0

13° Quel calcul faire pour obtenir le numéro de colonne de la case n°9 ?

...Correction...

9 % 4

14° Quel calcul faire pour obtenir le numéro de ligne de la case n°9 ?

...Correction...

9 // 4

✎ 15° Comment trouver la colonne de la case 117 d'un plateau de jeu comportant 34 cases par ligne ?

✎ 16 (difficile)° On considère un plateau comportant 42 cases par ligne. Un monstre est dans la case 1432 et un héros dans la case 1417. Les deux sont-ils adjacents, c'est à dire sur deux cases situées directement l'une à côté de l'autre dans le plateau ?

3 - Dictionnaire et interface graphique

Vous avez vu comment stocker un contenu simple (comme 5 ou 28) dans une variable (dans l'activité précédente).

>>> a = 10 >>> a 10

On peut également avoir besoin de stocker plusieurs contenus ayant un thème commun :

  • les notes d'élèves lors d'un DS : pour tous les élèves, on doit stocker le nom et la note associée
  • Le contenu et l'état d'un sac : pour tous les objets, on doit stocker le nom de l'objet et l'état de l'objet.
3.1 DICTIONNAIRE : définition

Un dictionnaire est un tableau associatif. Un dictionnaire est une collection non ordonnée d'éléments (contrairement aux tableaux et n-uplets où les éléments sont ordonnés via leurs indices).

Il comporte donc des cases qui portent un nom et possèdent un contenu.

On nomme :

  • clé (key en anglais) le nom de la case.
  • valeur (value en anglais) le contenu de la case.

Voici un dictionnaire décrivant le contenu d'un ds : les clés sont les noms des élèves et les contenus les notes.

Clé "Alice" "Bob" "Charlie"
Valeur 13 8 12

On peut résumer cela ainsi par l'image ci-dessous : le nom du dictionnaire permet de trouver les clés du dictionnaire qui permettent de trouver les valeurs associées.

flowchart LR D([Variable notes]) --> M([conteneur-dictionnaire]) M -- Clé Alice --> A([13]) M -- Clé Bob --> B([8]) M -- Clé Charlie --> C([12])
3.2 DICTIONNAIRE : déclaration

Le type de l'objet dictionnaire (dictionary en anglais) dans Python se nomme dict.

Déclaration
  • Les éléments délimiteurs sont les accolades {}.
  • On fournit un couple (cle, valeur) en utilisant la syntaxe Python suivante : clevaleur.
  • Chaque couple est séparé des autres par une virgule.

Exemple avec le dictionnaire décrivant un devoir surveillé :

1
ds = {"Alice": 13, "Bob": 8, "Charlie": 12}
Déclaration d'un grand dictionnaire

Sachez qu'on peut déclarer un dictionnaire sur plusieurs lignes en tapant sur ENTREE après chaque virgule. Exemple :

1 2 3 4 5
ds = { "Alice": 13, "Bob": 8, "Charlie": 12 }
>>> ds = {"Alice": 13, "Bob": 8, "Charlie": 12} >>> type(ds) <class 'dict'>
Déclaration d'un dictionnaire vide

Deux solutions

>>> d = {} >>> d {} >>> d = dict() >>> d {}
3.3 DICTIONNAIRE : accéder à une valeur avec [cle]

Pour récupérer la valeur d'une case, il faut connaître sa clé. On accède à une valeur en tapant le nom du dictionnaire suivi de la clé entre crochets.

Attention, on place des crochets pour accéder, les accolades c'est pour la déclaration.

>>> ds = {"Alice": 13, "Bob": 8, "Charlie": 12} >>> ds["Alice"] 13 >>> ds["Charlie"] 12 >>> ds["Bob"] 8 >>> ds["Bob l'éponge"] KeyError: "Bob l'éponge"

Comme vous le voyez, si on fournit une clé inconnue, on déclenche une erreur, comme avec un mauvais indice pour un tableau.

Résumé :

  • Si d est un dictionnaire,
  • Si c est une clé valide dans le dictionnaire,
  • Alors d[c] est le contenu associé à la clé c du dictionnaire d,

Nous allons maintenant utiliser les dictionnaires en interaction avec une interface graphique.

17° On considère que la coordonnée x d'un vaisseau est contenue dans un dictionnaire data en étant associée à la clé 'x'.

15 16
# 2 - CONSTANTES et variables globales ============================================ data = {'x': 100, 'y': 50} # Dictionnaire stockant les données modifiables

Question

  • Après lancement du programme, que faut-il taper dans la console pour incrémenter la valeur courante de la coordonnée x du curseur ?
  • Comment obtenir ensuite, via la console, la nouvelle valeur de cette coordonnée ?

...Correction...

>>> data['x'] = data['x'] + 1 >>> data['x'] 101
Choisir votre module graphique pour la suite :
3.4 Principe d'un programme pyxel

Logo Pyxel
Logo Pyxel

Le principe de fonctionnement d'un programme utilisant le module pyxel est basé sur une séquence qui inclut une boucle infinie.

Déroulé fondamental

On peut résumer le déroulé d'un programme Pyxel de cette façon 

  • Séquence de réglage : init() puis run()
  • 30 fois par seconde : controle() puis vue()
Déroulé plus détaillé

    1 - La fonction init() crée la fenêtre graphique.

    2 - La fonction run() active l'alternance infinie ci dessous :

    3 - TANT QUE le programme est actif :

      On mémorise les actions de l'utilisateur

      SI la dernière activation date de plus de 1/30e de seconde

        On active la fonction controle() qui va

        faire appel à différentes fonctions pour mettre à jour les données

        On active la fonction vue() qui va

        faire appel à cls() pour effacer l'écran

        faire appel à des fonctions afficher_...() pour afficher des formes à l'écran

      Fin du SI

    Fin TANT QUE

Système d'axes

Le point (0,0) est le bord haut gauche.

L'abscisse va bien vers la gauche.

Par contre, l'ordonnée est orientée vers le bas, attention.

Les axes dans Pyxel

18 (pyxel)° Vérifier si le module pyxel est installé :

>>> import pyxel

Si cela ne fonctionne pas, installer la bibliothèque pyxel dans Thonny :

  • Allez dans l'onglet "Outils"
  • Cherchez "Gérer les paquets"
  • Lancez la recherche sur pyxel puis activer l'installation
  • Attendez que l'installation soit totalement effectuée
  • Validez l'installation en utilisant le bouton Fermer

Une fois avoir vérifié que le module soit bien installé, placer en mémoire et lancer le programme suivant.

Vérifier que vous parvenez à faire bouger le vaisseau à l'aide des touches flèches gauche et droite.

L'analyse total du programme sera réalisée dans quelques activités, pour l'instant, vous n'allez avoir besoin que de survoler les différentes lignes.

Questions

  • Lignes 21-27 : qu'envoie-t-on à la fonction maj_position_vaisseau() lorsqu'on appuie sur la flèche DROITE ?
  • Lignes 29-36 : Pourquoi le vaisseau ne peut-il pas sortir totalement de l'écran ?
  • Modifier la fonction maj_position_vaisseau() pour que le vaisseau soit bien bloqué dès que son coin droit touche l'écran à droite : pour l'instant, il sort un peu trop...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
""" Module de présentation des interfaces Homme-machine (ihm) basée sur pyxel On découpe les fonctions en 3 catégories : - celles du MODELE [M], la mise à jour (maj) des données - celles de la VUE [V], la gestion de ce qu'on montre à l'utilisateur - celles du CONTROLEUR [C], la logique liée aux actions de l'utilisateur """ # 1 - Importations ============================================================ import pyxel # 2 - CONSTANTES et variables globales ======================================== data = {'x': 100, 'y': 50} # Dictionnaire stockant les données modifiables # 3 - FONCTIONS =============================================================== def controle(): """[C] Fonction qui récupère l'action, modifie les données en conséquence""" if pyxel.btn(pyxel.KEY_LEFT): maj_position_vaisseau(-1, 0) # Modifie en mémoire la position du vaisseau if pyxel.btn(pyxel.KEY_RIGHT): maj_position_vaisseau(1, 0) # Modifie en mémoire la position du vaisseau def maj_position_vaisseau(dx, dy): """[M] Modifie les données du vaisseau pour intégrer le déplacement dx et dy voulu""" data['x'] = data['x'] + dx if data['x'] > 128: data['x'] = 127 if data['x'] < 0: data["x"] = 0 def vue(): """[V] création des objets (30 fois par seconde)""" pyxel.cls(0) # vide la fenetre afficher_vaisseau(data['x'], data['y']) # vaisseau (carre 8x8) def afficher_vaisseau(x, y): """[V] Dessine et mémorise un nouveau vaisseau en (x,y)""" pyxel.rect(x, y, 8, 8, 1) # carré 8x8 et en couleur 1 # 4 - PROGRAMME PRINCIPAL ==================================================== pyxel.init(128, 128, title="Mon premier jeu") pyxel.run(controle, vue)

...Correction...

Il suffit de remplacer la limite fixée à 128 sur les lignes 33-34 à une valeur plus faible, 120 par exemple.

3.4 Principe d'un programme tkinter

Le principe de fonctionnement d'un programme utilisant le module tkinter est basé sur la séquence suivante qui inclut une boucle infinie :

    1 - La fonction Tk() crée la fenêtre graphique.

    2 - La méthode bind() permet de faire le lien entre un événement et une fonction de contrôle controle_...() de l'événement

    3 - La méthode mainloop() lance la surveillance en boucle des événements

    4 - TANT QUE le programme est actif :

      SI l'utilisateur appuie sur une touche, on active la fonction controle_...() correspondante qui va

        D'abord déterminer comment faire appel aux fonctions maj_...() pour modifier les modèles

        Ensuite demander à modifier l'affichage (la vue) en faisant appel à vue() qui va

        faire appel à delete() pour effacer l'écran

        faire appel à des fonctions afficher_...() pour afficher des formes à l'écran

      Fin du SI

    Fin TANT QUE

On peut résumer cela en 

  • Séquence de réglage : bind() puis mainloop()
  • Dès qu'un événement survient : controle_...() puis vue()

18 (tkinter)° Vérifier si le module tkinter est installé :

>>> import tkinter

Si cela ne fonctionne pas, installer la bibliothèque tkinter dans Thonny :

  • Allez dans l'onglet "Outils"
  • Cherchez "Gérer les paquets"
  • Lancez la recherche sur tkinter puis activer l'installation
  • Attendez que l'installation soit totalement effectuée
  • Validez l'installation en utisant le bouton Fermer
.

Une fois avoir vérifié que le module soit bien installé, placer en mémoire et lancer le programme suivant.

Vérifier que vous parvenez à faire bouger le vaisseau à l'aide des touches flèches gauche et droite.

L'analyse total du programme sera réalisée dans quelques activités, pour l'instant, vous n'allez avoir besoin que de survoler les différentes lignes.

Questions

  • Lignes 22-32 : qu'envoie-t-on à la fonction maj_position_vaisseau() lorsqu'on appuie sur la flèche DROITE ?
  • Lignes 34-41 : Pourquoi le vaisseau ne peut-il pas sortir totalement de l'écran ?
  • Modifier la fonction maj_position_vaisseau() pour que le vaisseau soit bien bloqué dès que son coin droit touche l'écran à droite : pour l'instant, il sort un peu trop...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
""" Module de présentation des interfaces Homme-machine (ihm) basée sur tkinter On découpe les fonctions en 3 catégories : - celles du MODELE [M] : la mise à jour (maj) des données - celles de la VUE [V] : la gestion de ce qu'on montre à l'utilisateur - celles du CONTROLEUR [C] : la logique liée aux actions de l'utilisateur """ # 1 - Importations ============================== from tkinter import Tk # pour créer la fenetre de jeu from tkinter import Canvas # pour créer la zone de dessin # 2 - CONSTANTES et variables globales ============================================ data = {'x': 100, 'y': 50} # Dictionnaire stockant les données modifiables # 3 - FONCTIONS ================================================================== def controle(evenement): """[C] Fonction qui récupère l'action, modifie les données en conséquence puis la vue""" touche = evenement.keysym # touche utilisée (Left, Right, Up, Left) if touche == "Left": # Si l'utilisateur appuie sur FLECHE LEFT maj_position_vaisseau(-3, 0) # Modifie en mémoire la position du vaisseau if touche == "Right": maj_position_vaisseau(3, 0) # Modifie en mémoire la position du vaisseau vue() def maj_position_vaisseau(dx, dy): """[M] Modifie les données du vaisseau pour intégrer le déplacement dx et dy voulu""" data['x'] = data['x'] + dx if data['x'] > 500: data['x'] = 500 if data['x'] < 0: data["x"] = 0 def vue(): """[V] Efface puis dessine la nouvelle vue""" plateau.delete("all") # Efface les dessins dans le canvas afficher_vaisseau(data['x'], data['y']) def afficher_vaisseau(x, y): """[V] Dessine et mémorise un nouveau vaisseau en (x,y)""" plateau.create_rectangle(x, y, x+20, y+20, fill="blue", width=0) # 4 - PROGRAMME PRINCIPAL ============================ fenetre = Tk() # Référence de la fenètre graphique fenetre.title("Mon premier jeu") fenetre.geometry("600x600") plateau = Canvas(fenetre) # Référence de la zone du plateau de jeu plateau.configure(width=500) plateau.configure(height=500) plateau.configure(bg="ivory") plateau.place(x=50, y=50) vue() # Dessine le vaisseau à la position initiale fenetre.bind("<Any-KeyPress>", controle) # Lie le clavier à la fonction fournie fenetre.mainloop() # Lance la surveillance des événements

...Correction...

Il suffit de remplacer la limite fixée à 500 sur les lignes 39-40 à une valeur plus faible, 480 par exemple.

4 - Résolution à l'aide d'une simple division euclidienne

Choisir votre module graphique pour la suite :

✎ 19 (pyxel)° Notre fenêtre d'application graphique comporte un écran de 128 sur 128 pixels.

Question

Modifier la fonction maj_position_vaisseau() pour que le vaisseau apparaisse à droite lorsqu'on va trop loin à gauche et à gauche lorsqu'on va trop loin à droite.

Vous proposerez DEUX SOLUTIONS :

  • L'une utilisera des if pour modifier x
  • L'autre utilisera le reste d'une division euclidienne pour modifier x

✌ 20 (pyxel)° Notre fenêtre d'application graphique comporte un écran 128x128. On imagine un plateau imaginaire de 10 colonnes sur 10 lignes, toutes numérotées de 0 à 9.

Question : modifier vue() pour lui ajouter une nouvelle fonctionnalité : elle doit afficher à l'aide de la fonction native print() d'abord la colonne du curseur, puis la ligne du curseur.

Vous pouvez commencer par rajouter une ligne de ce type qui va vous afficher simplement la position x et la position y du curseur.

x
print(data['x'] , " - ", data['y'])

✎ 19 (tkinter)° Notre fenêtre d'application graphique comporte un écran de 500 sur 500.

Question

Modifier la fonction maj_position_vaisseau() pour que le vaisseau apparaisse à droite lorsqu'on va trop loin à gauche et à gauche lorsqu'on va trop loin à droite.

Vous proposerez DEUX SOLUTIONS :

  • L'une utilisera des if pour modifier x
  • L'autre utilisera le reste d'une division euclidienne pour modifier x

✌ 20 (tkinter)° Notre fenêtre d'application graphique comporte un écran de 500 sur 500. On imagine un plateau imaginaire de 10 colonnes sur 10 lignes, toutes numérotées de 0 à 9.

Question : modifier vue() pour lui ajouter une nouvelle fonctionnalité : elle doit afficher à l'aide de la fonction native print() d'abord la colonne du curseur, puis la ligne du curseur.

Vous pouvez commencer par rajouter une ligne de ce type qui va vous afficher simplement la position x et la position y du curseur.

x
print(data['x'] , " - ", data['y'])

🏠 Exercices supplémentaires° Réaliser le Devoir Maison (voir le lien) en rédigeant correctement vos réponses.

DM à réaliser (17 questions)

5 - FAQ (Frequently Asked Questions)

J'ai vu une erreur sur le site, comment la signaler ?

Utilisez le bouton CONTACT en bas de chaque page.

Notez l'URL de l'activité ou son nom et copiez le texte qui pose problème, si besoin avec une description de ce qu'il faut changer si vous pensez que c'est nécessaire.

Merci !

Peut-on avoir des explications sur le programme qui dessine le curseur ?

Le programme est fourni après les explications.

Etape 1

1 2 3 4 5 6 7 8 9 10 11 12
"""Module de présentation des interfaces Homme-machine Basé sur Tkinter, il découpe les fonctions en 3 catégories : - celles qui modifient les DONNEES du jeu - celles qui modifient les GRAPHIQUES du jeu - celles qui permettent l'interaction entre DONNEES - GRAPHIQUES - UTILISATEUR """ # 1 - Importations ============================== from tkinter import Tk # pour créer la fenetre de jeu from tkinter import Canvas # pour créer la zone de dessin

On commence en lignes 11 et 12 par importer des modules supplémentaires permettant de réaliser des choses qui ne sont pas intégrées de base à Python. Ici, on importe depuis le module tkinter les constructeurs des fenêtres graphiques Tk et des zones de dessin Canvas.

Etape 2
14 15 16 17 18 19 20 21 22
# 2 - CONSTANTES et variables globales ============================================ donnees = {} # Permettra de stocker les données du jeu donnees["curseur_x"] = 250 donnees["curseur_y"] = 450 ref_ihm = {} # Permettra de stocker les références des affichages ref_ihm["dessin_curseur"] = 0

On crée deux dictionnaires qui vont contenir

  • pour l'un, les données du jeu et
  • pour l'autre, les références des objets graphiques (nommés widgets, contraction de window et gadget)

Etape 3

Ensuite, on ne regarde pas réellement les fonctions : il s'agit juste de déclaration. Le réflexe est plutôt d'aller en fin de programme pour tenter de voir ce qu'il fait.

A FINIR

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
"""Module de présentation des interfaces Homme-machine Basé sur Tkinter, il découpe les fonctions en 3 catégories : - celles qui modifient les DONNEES du jeu - celles qui modifient les GRAPHIQUES du jeu - celles qui permettent l'interaction entre DONNEES - GRAPHIQUES - UTILISATEUR """ # 1 - Importations ============================== from tkinter import Tk # pour créer la fenetre de jeu from tkinter import Canvas # pour créer la zone de dessin # 2 - CONSTANTES et variables globales ============================================ donnees = {} # Permettra de stocker les données du jeu donnees["curseur_x"] = 250 donnees["curseur_y"] = 450 ref_ihm = {} # Permettra de stocker les références des affichages ref_ihm["dessin_curseur"] = 0 # 3 - Déclaration des fonctions gérant les DONNEES ================================ def modifier_coordonnees_curseur(dpc_x): """Modifie les données x du vaisseau pour intégrer le déplacement dpc_x voulu""" donnees["curseur_x"] = calculer_coordonnees_curseur(donnees["curseur_x"], dpc_x) def calculer_coordonnees_curseur(x, dpc_x): """Calcule et renvoie la nouvelle coordonnée x après un déplacement dpc_x""" x = x + dpc_x if x > 500: x = 500 if x < 0: x = 0 return x # 4 - Déclaration des fonctions purement GRAPHIQUES ================================ def dessiner_curseur(x, y): """Efface le vaisseau actuel, dessine le nouveau en (x,y) et renvoie sa référence""" # Extraction des DONNEES utiles pour cette fonction fenetre = ref_ihm["fenetre"] # Récupération de la référence de la fenêtre plateau = ref_ihm["plateau"] # Récupération de la référence du plateau curseur = ref_ihm["dessin_curseur"] # Récupération de l'identifiant du dessin du curseur # Suppression du dessin du curseur plateau.delete(fenetre, curseur)Description du plateau # Dessine et mémorise l'id du nouveau ref_ihm["dessin_curseur"] = plateau.create_rectangle(x, y, x+20, y+20, fill="blue", width=0) # 5 Déclaration des fonctions EVENEMENTIELLES : interaction données, graphiques, utilisateur ==== def gestion_clavier(evenement): """Fonction événementielle qui gère les actions après appui sur une touche""" # Effets sur les DONNEES touche = evenement.keysym # Extraction de la touche depuis l'événément if touche == "Left": # Si l'utilisateur appuie sur FLECHE UP modifier_coordonnees_curseur(-3) # Modifie en mémoire la position du curseur elif touche == "Right": modifier_coordonnees_curseur(3) # Modifie en mémoire la position du curseur # remarque : 'Up' et 'Down' pour les autres flèches # Extraction des DONNEES utiles pour cette fonction x = donnees["curseur_x"] y = donnees["curseur_y"] # Effets sur l'AFFICHAGE dessiner_curseur(x, y) # 4 - PROGRAMME PRINCIPAL ============================ fenetre = Tk() fenetre.title("Mon premier jeu") fenetre.geometry("600x600") ref_ihm["fenetre"] = fenetre plateau = Canvas(fenetre) plateau.configure(width=500) plateau.configure(height=500) plateau.configure(bg="ivory") plateau.place(x=50, y=50) ref_ihm["plateau"] = plateau dessiner_curseur(donnees["curseur_x"], donnees["curseur_y"]) fenetre.bind("<Any-KeyPress>", gestion_clavier) fenetre.mainloop()

Voici pour ce premier contact avec la console de Python.

Pour la plupart des activités, vous trouverez un récapitulatif des notions à connaître. Il ne s'agit d'un ensemble de questions auxquelles il faudra savoir répondre si vous voulez une bonne note.

Le résumé de l'activité regroupe lui l'ensemble des points de cours, les encarts verts .

LIEN VERS LES RECAPITULATIFS

LIEN VERS LES RESUMES

Activité publiée le 28 08 2019
Dernière modification : 15 07 2023
Auteur : ows. h.