# source_cell

id: 384448c390374e83b372e7168ce354c2
name: cell-bc2bac01a1ae5d6e
cell_type: markdown
checksum: f003d1fe379fe84ce034a14aea0c8147
notebook_id: 27554e4e09344f9992877a8ad6372bbd
source:
  # Modularité, compilation séparée

  Rappelez-vous notre **livre de recettes**. À l'époque, nous avons vu
  comment **découper un programme en fonctions** pour plus de
  **modularité**.  Cela permet de mieux le comprendre, petit bout par
  petit bout, d'éviter les redites, etc.

  Nous allons de même **découper un programme en plusieurs fichiers**.


id: 77e40cef5fcd4864bec9fdca054ae869
name: cell-eda0e2d6022d648c
cell_type: markdown
checksum: 1492e87493155542d8d49436f01e4b91
notebook_id: 27554e4e09344f9992877a8ad6372bbd
source:
  ``` c++
  #include <iostream>
  using namespace std;

  int monMax(int a, int b) {
      if ( a >= b )
          return a;
      else
          return b;
  }
  ```
  ``` c++
  int main() {
      cout << monMax(1, 3) << endl;
      return 0;
  }
  ```


id: 98c3032aa91b4ee08784fbbc43b34183
name: cell-04d9ac7b73aa7156
cell_type: markdown
checksum: bcc5994c592a52d4141024a74fe4ad11
notebook_id: 27554e4e09344f9992877a8ad6372bbd
source:
  Contenu du fichier `max.hpp` :
  ``` c++
  /** La fonction max
   *  @param x, y deux entiers
   *  @return un entier,
   *  le maximum de x et de y
   **/
  int monMax(int a, int b);
  ```


id: 57b13cfb23534e59a106eeceda272c14
name: cell-c0ee9ca9166c339g
cell_type: markdown
checksum: 12530a4d02fe03e35ea980f1ee58d2b0
notebook_id: 27554e4e09344f9992877a8ad6372bbd
source:
  Contenu du fichier `max-test.cpp` :
  ``` c++
  #include <iostream>
  using namespace std;

  #include "max.hpp"

  /** Infrastructure minimale de test **/
  #define CHECK(test) if (!(test)) cerr << "Test failed in file " << __FILE__ << " line " << __LINE__ << ": " #test << endl
  ```
  ``` c++
  void monMaxTest() {
      CHECK( monMax(2,3) == 3 );
      CHECK( monMax(5,2) == 5 );
      CHECK( monMax(1,1) == 1 );
  }

  int main() {
      monMaxTest();
  }
  ```


id: acf06421423647499c2a2afd5b2205cc
name: cell-26e5cd21217b8ec5
cell_type: markdown
checksum: b3709f14a593cf15abcc96057044e99f
notebook_id: 27554e4e09344f9992877a8ad6372bbd
source:
  #### Compilation séparée (1)

  -   Un programme peut être composé de plusieurs ***fichiers source***  
      Contenu :
      -   Des *définitions* de fonctions
      -   Des variables globales, ...

  -   Chaque fichier source est compilé en un ***fichier objet*** (extension : .o)  
      Contenu :
      -   Le code binaire des fonctions, ...

  -   L'*éditeur de liens* combine plusieurs fichiers objet en un
      *fichier exécutable*


id: 327e917a6f1648aebd6d35bf6a4b4151
name: cell-de97499851e34054
cell_type: markdown
checksum: 0d83630ea4ed4d5d557e122d963571f8
notebook_id: 27554e4e09344f9992877a8ad6372bbd
source:
  #### Compilation séparée (2)

  **Au moment de l'édition de lien :**

  -   Chaque fonction utilisée doit être définie une et une seule fois
  -   La fonction `main` doit être définie une et une seule fois


id: fa1f01e558e845a88ae44ab94714b219
name: cell-de97499851e34055
cell_type: markdown
checksum: ce17de7f5b94f7bb286b8110e5437571
notebook_id: 27554e4e09344f9992877a8ad6372bbd
source:
  **Quelques variantes autour des fichiers objets :** ♣

  -   Bibliothèques (.a) :
      Une archive contenant plusieurs fichiers objets .o

  -   Bibliothèques dynamiques (.so) :
      Édition de lien dynamique au lancement du programme


id: 47e9697916e9478fa8d0d68897909d52
name: cell-e568b9b55cb70a3b
cell_type: markdown
checksum: 52664d050cdb13f6a766e3cbcc175719
notebook_id: 27554e4e09344f9992877a8ad6372bbd
source:
  #### Fichiers d'entête

  Fichier `.hpp` (ou `.h` en C) contenant la *déclaration* des fonctions *définies* dans
  le fichier `.cpp` correspondant


id: eba092cd1f8343199fa08af5fd237434
name: cell-e568b9b55cb70a3d
cell_type: markdown
checksum: 1e9959987853b8d9ed69ad76b649bbe2
notebook_id: 27554e4e09344f9992877a8ad6372bbd
source:
  **Syntaxe :** Utilisation d'un fichier d'entête

  ``` c++
  #include "max.hpp"
  ```

  **Sémantique :**

  Utiliser la bibliothèque `max`


id: 65eaec3cd9ba49b1919d53ebf4e7f586
name: cell-e568b9b55cb70a3e
cell_type: markdown
checksum: 7c7bbb13cb5d1fe766e13d181ac0e393
notebook_id: 27554e4e09344f9992877a8ad6372bbd
source:
  **Implantation en C++ :**
  -   Équivalent à copier-coller le contenu de `max.hpp` à l'emplacement du
      `#include "max.hpp"`
  -   ♣ Géré par le préprocesseur (cpp)


id: 87a65c1bbb8348839853982ef7ac9958
name: cell-1501d26cad5b60f2
cell_type: markdown
checksum: ff72d7aa40bd416b2c3dacc17f4839cb
notebook_id: 27554e4e09344f9992877a8ad6372bbd
source:
  #### Inclusion de fichiers d'entêtes standards

  **Syntaxe :**

  ``` c++
  #include <iostream>
  ```

  **Sémantique :**
  -   Charge la déclaration de toutes les fonctions définies dans la
      bibliothèque standard `iostream` de C++

  -   Le fichier `iostream` est recherché dans les répertoires standards
      du système

  -   Sous linux : `/usr/include`, ...


id: ecf90cf9065949e2ad654fc221f001ff
name: cell-208ec2ed61304263
cell_type: markdown
checksum: d26c3cdec520f8f76b0624b17f950fe6
notebook_id: 27554e4e09344f9992877a8ad6372bbd
source:
  **Écrire un fichier d'entête (max.hpp) :**

  -   La déclaration de toutes les fonctions publiques
  -   *Avec leur documentation !*


id: 0e3fca831d934ebeb361dfea746b1e74
name: cell-208ec2ed61304264
cell_type: markdown
checksum: 9b390f6d19d63b7222aaf3e9ea2c2733
notebook_id: 27554e4e09344f9992877a8ad6372bbd
source:
  **Écrire un fichier source (max.cpp) :**

  -   La définition de toutes les fonctions
  -   *Inclure le fichier .hpp !*


id: 35496dfd941d4d1693302488a91214a0
name: cell-208ec2ed61304265
cell_type: markdown
checksum: b16ddc2f444fbd91507b32f1ad2bb135
notebook_id: 27554e4e09344f9992877a8ad6372bbd
source:
  **Écrire un fichier de tests (maxTest.cpp) :**

  -   Les fonctions de tests
  -   Une fonction `main` lançant tous les tests


id: fe9c2a0d4e9743438bf3ea26308bafb6
name: cell-bcde2b57c973b401
cell_type: markdown
checksum: e481920f06b39675a98584449d963d6a
notebook_id: 27ba8f78dcfb459886b03349aa80859d
source:
  :::{admonition} Notes aux enseignants

  Avec la compilation séparée, et surtout les graphismes, cette semaine
  est un peu technique. Il est très important de tester le TP en salle
  TP et sur JupyterHub.

  2022-2023: sfml n'est pas (à ce stade) installé par défaut en salle
  TP. Il faut donc l'installer dans l'environnement info-111 :

  ```shell
  info-111 run bash
  mamba install sfml
  ```

  D'où l'instruction de compiler avec `info-111 compile` dans l'exercice sur
  les graphismes.

  Il y a aussi un problème de bibliothèque libudev.so.0 manquante. Ce
  problème peut être contourné avec :

  ```shell
  mamba install -c conda-forge libudev
  cd $CONDA_PREFIX/lib
  ln -s libudev.so.1 libudev.so.0
  ```

  TODO 2023-2024:
  - basculer à xcanvas
  - utiliser la libsfml sur le hub maintenant que XFCE Desktop est
    disponible. Voir
    https://gitlab.dsi.universite-paris-saclay.fr/jupyterhub-paris-saclay/image/-/issues/8 .

  :::


id: b5c829be997d4aefa49d39097fdff111
name: cell-6d952c4decd8c707
cell_type: markdown
checksum: f117371d70884a7bf3ba7d2cd02a4af7
notebook_id: 27ba8f78dcfb459886b03349aa80859d
source:
  ## Objectifs pédagogiques

  Cette semaine, comme la précédente, notre objectif est de gérer de
  **« gros » programmes**, notamment pour continuer à vous préparer au
  projet. Nous avions eu un premier aperçu du concept de **modularité**,
  en découpant un programme en **fonctions**. Nous allons en rajouter
  une couche en découpant un programme en plusieurs fichiers, grâce à la
  **compilation séparée**. En prélude, nous discuterons le **cycle de
  vie d'un programme**, notamment pour clarifier ce qu'est la
  **compilation**.  Comme application nous utiliserons <!-- si les
  conditions techniques à distance nous le permettent !-->la
  **bibliothèque multimédia SFML** pour faire des dessins et des
  interfaces graphiques. Cela pourra servir pour certaines parties
  optionnelles du projet.

  En TD et TP, nous mettrons d'abord en application la compilation
  séparée, observant en détail un programme découpé en plusieurs
  fichiers, puis reproduisant le schéma pour découper un autre programme
  en plusieurs fichiers. Puis nous étudierons quelques exemples de
  programmes utilisant la bibliothèque SFML et nous en inspirerons pour
  programmer des dessins et interagir avec l'utilisateur.


id: 49b464c3cd8948568fa1eaf221993b52
name: cell-6d952c4decd8c706
cell_type: markdown
checksum: 1944ac8026cc545a57bcc39a8d55fe63
notebook_id: 27ba8f78dcfb459886b03349aa80859d
source:
  ## <a name=Cours>Cours</a>

  - Cours : [Cycle de vie d'un programme](cours-cycle-de-vie-d-un-programme.md)
  - Cours : [Modularité et compilation séparée](cours-modularite.md)
  - Cours : [Digressions: surcharge, templates, espaces de noms](cours-digressions.md)
  - Cours : [Conclusion](cours-conclusion.md)


id: c5860d5c9fd54ce2b0800c4f21231dc3
name: cell-88edc2f254ba7294
cell_type: markdown
checksum: b3fecc2d15e9c0ee06eddcefbb2ad19a
notebook_id: 27ba8f78dcfb459886b03349aa80859d
source:
  ### Exercice : préliminaires : compilation séparée

  1.  Consultez le contenu des fichiers suivants : [factorielle.hpp](factorielle.hpp),
      [factorielle.cpp](factorielle.cpp), [factorielle-exemple.cpp](factorielle-exemple.cpp).

  2.  Compilez le programme entier en suivant les instructions suivantes.
      Commencez par compiler chacun des bouts de programme (fichiers `.cpp`).
      Pour cela on utilise l'option `-c` :
      ```shell
      clang++ -c factorielle.cpp
      clang++ -c factorielle-exemple.cpp
      ```

      Ceci nous a créé deux fichiers, `factorielle.o` et
      `factorielle-exemple.o` qui sont des bouts de programme binaires.
      Vérifiez avec `ls` que ces fichiers ont bien été créés.

      Combinez ensuite (en anglais: *link* pour «édition de liens»)
      ces deux bouts de programme de la façon suivante :
      ```shell
      clang++ factorielle.o factorielle-exemple.o -o factorielle-exemple
      ```

      Vérifiez avec `ls` que cette commande crée bien un exécutable
      `factorielle-exemple`.

  4.  Exécutez le programme `factorielle-exemple`.

  5.  Consultez le fichier [factorielle-test.cpp](factorielle-test.cpp).
      Créez un exécutable `factorielle-test` en adaptant les étapes
      ci-dessus, puis testez ce nouveau programme.

  6.  Une autre méthode pour compiler `factorielle-exemple` est de
      remplacer les trois commandes de la question (2) par la seule
      commande :
      ```shell
      clang++ factorielle.cpp factorielle-exemple.cpp -o factorielle-exemple
      ```

      Supprimez les fichiers `factorielle.o`, `factorielle-exemple.o` et
      `factorielle-exemple` de votre dossier avec `rm`. Testez alors la
      commande précédente. Quel(s) fichier(s) ont été créés ? En déduire
      les différences avec la méthode précédente. Selon le cas vous pourrez
      être amené à choisir l'une ou l'autre, notamment dans le projet.


id: 8c6e0863d2234203a708af3768c2d33c
name: cell-bcde2b57c973b400
cell_type: markdown
checksum: 4926713763b0e145f25516bd63ae0fdd
notebook_id: 27ba8f78dcfb459886b03349aa80859d
source:
  :::{admonition} Notes aux enseignants

  Erreurs fréquentes :
  - Faute d'orthographe à fibonacci (typiquement nombre de n ou nombre de c)
    qui fait que le fichier n'est pas trouvé.
  - Ne pas mettre l'include du `.hpp` dans tous les `.cpp` (ou inclure
    `factorielle.hpp` au lieu de `fibonacci.hpp`, ou mettre des `< >` au
    lieu des `" "`).
  - Faire un `.hpp` qui contient uniquement la documentation de la
    fonction mais pas son en-tête.
  - Certains laissent le lancement des tests dans le `main` de
    `fibonacci-exemple.cpp` ce qu'ils ne sont pas censés faire (cf. le
    modèle donné pour factorielle) et pose le problème de la déclaration
    de la fonction de test.
      
  :::


id: debc79fba2fb455aaa8be82fc5833587
name: cell-89f33130471fc08e
cell_type: markdown
checksum: 0aa22e643a0731f21a052d645349ad26
notebook_id: 27ba8f78dcfb459886b03349aa80859d
source:
  -   Ouvrez le fichier [fibonacci.cpp](fibonacci.cpp) et regardez son
      contenu. Remarquez que la fonction `main` mélange deux actions de
      nature très différente : d'une part lancer les tests de la
      fonction `fibonacci`, et d'autre part utiliser cette fonction pour
      interagir avec l'utilisateur. Ceci n'est pas très satisfaisant.

  -   Réorganisez le fichier [fibonacci.cpp](fibonacci.cpp) en plusieurs
      fichiers en suivant le modèle de l'exercice précédent. Il y aura
      donc quatre fichiers :
  	- [fibonacci.hpp](fibonacci.hpp),
      - [fibonacci.cpp](fibonacci.cpp),
      - [fibonacci-test.cpp](fibonacci-test.cpp),
      - [fibonacci-exemple.cpp](fibonacci-exemple.cpp).

      Faites attention à ne pas dupliquer de code.


id: f913bd4ceeda4049a594ccca0bb88392
name: cell-89f33130471fc08f
cell_type: markdown
checksum: ed2c4d1d7c8b563e2a33580c914aa9d6
notebook_id: 27ba8f78dcfb459886b03349aa80859d
source:
  -   Quels exécutables allez-vous construire? Pour chaque exécutable,
      quels fichiers allez-vous combiner pour l'obtenir ? Vérifiez
      pour chaque exécutable que chaque fonction utilisée (dont la
      fonction `main`) est définie une et une seule fois dans l'ensemble
      de fichiers correspondant.


id: 790f03412b8143428813e820a3fe968b
name: cell-89f33130471fc08g
cell_type: markdown
checksum: eb352fd592187fcac4ce19570c7bc952
notebook_id: 27ba8f78dcfb459886b03349aa80859d
source:
  -   Compilez chacun des deux programmes (test et exemple) grâce à la
      compilation séparée, exécutez les et vérifiez que tout fonctionne
      correctement. En cas d'erreur, lisez le message d'erreur puis
      comparez attentivement vos fichiers et commandes avec ceux donnés
      pour la fonction `factorielle` (si vous avez la feuille de TD sous
      la main, l'énoncé de l'exercice 1 permet de visualiser facilement
      tous les fichiers pour factorielle).

      Notez ci-dessous les commandes utilisées pour la compilation :


id: 2f65c76f25d34bbf8c790c6bac09840a
name: cell-96bafcc3c30ace6e
cell_type: markdown
checksum: 7c740bf5fd075394305a0f98d1dd0422
notebook_id: 27ba8f78dcfb459886b03349aa80859d
source:
  ### Exercice : Premiers graphiques avec Jupyter

  1.  Refaites l'exercice 2 du [TD](TD.md) en complétant la feuille
      [premier-dessin](premier-dessin.md). Implantez chacun des items
      en vérifiant à chaque fois le résultat.


id: 461edde040024f94898a15983760a8b6
name: cell-96bafcc3c30ace6f
cell_type: markdown
checksum: e883c664c0706a830228145c1004b74a
notebook_id: 27ba8f78dcfb459886b03349aa80859d
source:
  ### Exercice : Premiers graphiques avec SFML ♣

  :::{attention}

  Il n'est à l'heure actuelle pas encore possible d'utiliser le serveur
  JupyterHub pour cet exercice. Il est donc à effectuer en local en
  salle de TP (ou sur votre machine personnelle si vous avez les
  logiciels requis). Si vous n'avez pas eu le temps de le faire en
  séance de TP, ce n'est pas critique pour l'avancement de votre
  projet. Aussi est-il marqué d'un ♣.

  :::

  Pour installer les logiciels requis sur votre machine personnelle,
  voir les sections « Aide à l'installation » sur la [page logiciels du
  site du cours](http://nicolas.thiery.name/Enseignement/Info111/logiciels/#aide-installation).
  À noter que, pour utiliser la SFML sur CodeBlocks ou tout autre
  environnement de développement intégré (IDE),
  il faut configurer l'IDE. Plus encore que d'habitude, nous
  recommandons de compiler en ligne de commande dans le terminal. Pour
  l'instant, en salle de TP, il est nécessaire d'utiliser `info-111 compile`
  pour compiler un programme utilisant SFML.

  1.  Ouvrez les fichiers [exemple-graphisme1.cpp](exemple-graphisme1.cpp)
      et [primitives.hpp](primitives.hpp) et consultez le premier.

  2.  Compilez ce programme depuis le terminal avec
      (en une seule ligne !) :
      ```shell
      info-111 compile exemple-graphisme1.cpp primitives.cpp -o exemple-graphisme1 -lsfml-system -lsfml-window -lsfml-graphics
      ```

      Explication : le code binaire de SFML est réparti dans trois
      bibliothèques `sfml-system`, `sfml-window` et `sfml-graphics`.
      Les arguments `-lsfml-system`, ... indiquent au compilateur de les
      lier au programme (`-l` pour *link*).

  3.  Lancez le programme obtenu avec :
      ```shell
      ./exemple-graphisme1
      ````
  	Vous obtenez une fenêtre blanche, avec un (tout petit!) point
      rouge un peu à gauche, près du bord haut.

  4.  Compilez le programme fourni
      [premier-dessin.cpp](premier-dessin.cpp)
      en adaptant la commande utilisée plus haut pour compiler
      [exemple-graphisme1.cpp](exemple-graphisme1.cpp).
      Complétez [premier-dessin.cpp](premier-dessin.cpp) à partir
      de la feuille [premier-dessin](premier-dessin.md). N'hésitez pas
      à changer la valeur de la variable `delai` pour voir le résultat
      s'afficher plus longtemps.


id: ef9770bb957d42e893ff368d4b316d0a
name: cell-00e5e7435133ed7c
cell_type: markdown
checksum: 633dad6d2fc40907647239a4c8b48e31
notebook_id: 27ba8f78dcfb459886b03349aa80859d
source:
  :::{admonition} Notes aux enseignants

  Certains élèves croient que le premier caractère de `-lsfml-*` est un
  $1$ alors qu'il s'agit d'un $\ell$ (c'est vrai que ce n'est pas
  forcément très clair mais cela se voit en comparant avec les autres
  caractères de la ligne : on voit que ce n'est pas exactement le même
  caractère que dans `info-111` mais que c'est le même que dans `sfml`).

  Certains élèves compilent le programme `premier-dessin.cpp` en oubliant
  l'option `-lsfml*`, ce qui crée plein d'erreurs.

  :::


id: b433d0d081b34fc0a21b4dc1173ec76e
name: cell-eaefcdbc75785adb
cell_type: markdown
checksum: 851f78b272e43edba563532592fc2279
notebook_id: 27ba8f78dcfb459886b03349aa80859d
source:
  ### Exercice ♣ : Souris et clavier

  1.  Pour vous donner une idée de l'utilisation de la SFML et
      de notre bibliothèque de primitives, lisez attentivement
      [primitives.hpp](primitives.hpp) et sa documentation.

  2.  Consultez ensuite [exemple-graphisme2.cpp](exemple-graphisme2.cpp)
      et [exemple-graphisme3.cpp](exemple-graphisme3.cpp) pour en voir
      des exemples d'utilisation.

  3.  Implantez l'exercice 4 du TD.

      <!-- Solutions dans le TD !-->


id: 15626365aeec4604946b1c22e0e3c304
name: cell-5858dbcffa05aed3
cell_type: markdown
checksum: 5917c7b9cfd1dcba875ca0c00faa1060
notebook_id: 27ba8f78dcfb459886b03349aa80859d
source:
  ### Exercice ♣: Couche d'abstraction

  Pour vous approprier la couche d'abstraction, consultez son
  implantation dans `primitives.cpp`. En vous inspirant de
  ce qui est déjà fait, complétez l'implantation de la fonction
  `draw_filled_rectangle` (documentée dans `primitives.hpp`).
  Vous pouvez vous aider de la
  [documentation en ligne de la SFML](https://www.sfml-dev.org/learn-fr.php).


id: 75aaf6cf1aa346749e45d4e9237e0bc4
name: cell-48f3d0b08106b27e
cell_type: markdown
checksum: 346c0470eb0efbaa0d4446698ec913d5
notebook_id: 27ba8f78dcfb459886b03349aa80859d
source:
  ### Exercice  ♣: Jeu du Yams

  Reprenez le jeu du Yams du TP 6 en ajoutant une interface graphique.

  On affichera les dés (soit avec du texte, soit avec des points) dans
  la fenêtre. Revoyez [exemple-graphisme3.cpp](exemple-graphisme3.cpp)
  pour des fonctions rapides. L'utilisateur pourra cliquer sur les dés
  à combiner pour former une figure. (Utiliser par exemple `wait_mouse()`
  pour cliquer sur les dés, et `wait_keyboard()` pour valider.) Le nombre
  de points sera ensuite affiché.

  À vous de concevoir les fonctions à introduire pour décomposer le
  problème.


id: 2b5ae238b90b49aaac63f5bbd4ddadef
name: cell-e77db2d9ed7265ac
cell_type: code
checksum: b956b1c98520d602fab742ceb67096ed
notebook_id: 91d20baea24d4d7694ef930ea2d485d5
source:
  // Dessine un segment blanc entre les points (100,200) et (200,200)
  // REMPLACEZ CETTE LIGNE ET LA SUIVANTE PAR VOTRE RÉPONSE
  throw std::runtime_error("À faire");
  window.display();


id: a972812b09af40f380916276f2ae4d5e
name: cell-03b3d3f225c29d1d
cell_type: code
checksum: 85bdbd533e19a61d9a8a460522c51477
notebook_id: 91d20baea24d4d7694ef930ea2d485d5
source:
  // Dessine un segment rouge entre les points (200,300) et (200,400)
  // REMPLACEZ CETTE LIGNE ET LA SUIVANTE PAR VOTRE RÉPONSE
  throw std::runtime_error("À faire");
  window.display();


id: 3652ee6feb33414eb54ea974d8daf378
name: cell-3606e0158c83309d
cell_type: code
checksum: dea1bd15783375ceace4d093b9200ec4
notebook_id: 91d20baea24d4d7694ef930ea2d485d5
source:
  // Dessine un rectangle horizontal vide de sommets diagonaux (200,200) et (400,300) et de contour rouge
  // REMPLACEZ CETTE LIGNE ET LA SUIVANTE PAR VOTRE RÉPONSE
  throw std::runtime_error("À faire");
  window.display()


id: c6cbe7f66ece4893be374223b831ca66
name: cell-25abe8a7c6c8c617
cell_type: code
checksum: 8d1e034e1cda25ee20a1c154f6f26185
notebook_id: 91d20baea24d4d7694ef930ea2d485d5
source:
  // Dessine un rectangle horizontal plein noir de sommets diagonaux (400,150) et (500,200)
  // REMPLACEZ CETTE LIGNE ET LA SUIVANTE PAR VOTRE RÉPONSE
  throw std::runtime_error("À faire");
  window.display()


id: 7e4f07f37b7f4867938c8e5e168214ed
name: cell-c6d75131df2bea6d
cell_type: code
checksum: 196d46fbc53bc7393b523ace887864ab
notebook_id: 91d20baea24d4d7694ef930ea2d485d5
source:
  // Dessine un segment rouge entre les points (400,300) et (500,400)
  // REMPLACEZ CETTE LIGNE ET LA SUIVANTE PAR VOTRE RÉPONSE
  throw std::runtime_error("À faire");
  window.display()


id: 2ca617c130924364911bffa5665955e7
name: cell-63406c09d76b868b
cell_type: code
checksum: 783c0f2dd02e54533dd5243b34fe2ccd
notebook_id: 91d20baea24d4d7694ef930ea2d485d5
source:
  // Dessine un cercle noir de centre (415,145) et de rayon 10
  // REMPLACEZ CETTE LIGNE ET LA SUIVANTE PAR VOTRE RÉPONSE
  throw std::runtime_error("À faire");
  window.display()


id: 479d830d2b7041b1a951864f81a8cd63
name: cell-4f7332edb4646cbf
cell_type: code
checksum: cfc9ac790998bab53ad2de41b30f2f6d
notebook_id: 91d20baea24d4d7694ef930ea2d485d5
source:
  // Dessine un disque jaune de centre (700, 100) et de rayon 50
  // REMPLACEZ CETTE LIGNE ET LA SUIVANTE PAR VOTRE RÉPONSE
  throw std::runtime_error("À faire");
  window.display()


id: 19bc2955f4524b20ac96f09f591765a3
name: 10
cell_type: markdown
checksum: 810c04226cda9f4619e3d6c4d644b336
notebook_id: 3d4f0337cfb14542bd75470f682b424a
source:
  ::::{admonition} Exercice 1 : Compilation séparée

  Annotez les quatre fichiers suivants en précisant leurs rôles
  respectifs et en indiquant où se trouvent entête, définition,
  documentation, tests et utilisation de la fonction `factorielle`.

  :::{literalinclude} factorielle.hpp
  :caption: factorielle.hpp
  :::

  :::{literalinclude} factorielle.cpp
  :caption: factorielle.cpp
  :::

  :::{literalinclude} factorielle-test.cpp
  :caption: factorielle-test.cpp
  :::

  {latexonly}`\clearpage`

  :::{literalinclude} factorielle-exemple.cpp
  :caption: factorielle-exemple.cpp
  :::

  ::::

  % REMPLACEZ CETTE LIGNE PAR VOTRE RÉPONSE

  {latexonly}`\bigskip`
  {latexonly}`\enlargethispage{8ex}`

  ## Graphiques

  En TP, nous utiliserons la bibliothèque `SFML` [^1], une bibliothèque
  largement utilisée facilitant le développement de jeux ou
  d'applications multimédias grâce à une grande panoplie de modules
  (fenêtrage, graphismes, audio, réseau, ...), principalement développée
  par Laurent Gomila. Nous allons nous en servir pour créer une fenêtre
  et dessiner dedans.

  La `SFML` n'étant pas immédiatement intuitive à utiliser, nous avons
  écrit une micro bibliothèque composée de quelques primitives pour vous
  simplifier les premiers pas. Cette bibliothèque, documentée dans
  `primitives.hpp`, a vocation à être la plus transparente possible. À
  vous de la lire en détail pour vous l'approprier et, par la suite,
  vous en passer.

  Voici un exemple de programme utilisant la `SFML` et notre
  bibliothèque `primitives` :

  :::{literalinclude} exemple-graphisme1.cpp
  :caption: exemple-graphisme1.cpp
  :::

  Notez dans cet exemple le nouveau type `RenderWindow` représentant une
  fenêtre et les fonctions `clear` pour effacer la fenêtre, `sleep` pour
  attendre un temps donné et `draw_point` (qui vient de
  `primitives.cpp`) pour dessiner un point.


id: d89db88cf36b416d9b9e773e56d98661
name: 20
cell_type: markdown
checksum: 1986e35cfea627cd75aaacb627e8ad3c
notebook_id: 3d4f0337cfb14542bd75470f682b424a
source:
  ::::{admonition} Exercice 2 : Premiers dessins

  En vous inspirant de l'exemple fourni, écrivez des instructions
  (fragments de programme) qui, respectivement,

  1.  dessinent un point noir (*Black*) de coordonnées $(418, 143)$;

      % REMPLACEZ CETTE LIGNE PAR VOTRE RÉPONSE

  2.  dessinent un segment blanc (*White*) reliant les
      points $(100, 200)$ et $(200, 200)$;

      % REMPLACEZ CETTE LIGNE PAR VOTRE RÉPONSE

  3.  dessinent un segment rouge (*Red*) reliant les points $(200, 300)$ et
      $(200, 400)$;

      % REMPLACEZ CETTE LIGNE PAR VOTRE RÉPONSE

  4.  dessinent le rectangle horizontal vide de contour rouge dont les sommets diagonaux
      sont $(200, 200)$ et $(400, 300)$;

      % REMPLACEZ CETTE LIGNE PAR VOTRE RÉPONSE

  5.  dessinent un rectangle horizontal plein noir dont les sommets
      diagonaux sont $(400, 150)$ et $(500, 200)$;

      % REMPLACEZ CETTE LIGNE PAR VOTRE RÉPONSE

  6.  dessinent un segment rouge reliant les points $(400, 300)$ et
      $(500, 400)$;

      % REMPLACEZ CETTE LIGNE PAR VOTRE RÉPONSE

  7.  dessinent un cercle noir de centre $(415, 145)$ et de rayon
      $10$;  
  	**Indication :** Utiliser les fonctions `cos` et `sin`.

      % REMPLACEZ CETTE LIGNE PAR VOTRE RÉPONSE

  8.  dessinent un disque jaune (*Yellow*) de centre $(700, 100)$ et de rayon
      $50$;  
  	**Indication :** Utiliser la définition d'un disque.

      % REMPLACEZ CETTE LIGNE PAR VOTRE RÉPONSE

  ::::


id: 3971cbfa18294d9482fd6efcb452f21c
name: 30
cell_type: markdown
checksum: be45863a53351171a30bb896289f3266
notebook_id: 3d4f0337cfb14542bd75470f682b424a
source:
  {latexonly}`\enlargethispage{2ex}`

  ::::{admonition} Exercice 3 : $\clubsuit$ Fonctions de dessin

  Notre bibliothèque `primitives` contient entre autres les fonctions
  suivantes :

      /** Affiche une ligne de couleur entre deux positions données
       * @param w une fenêtre ouverte dans laquelle dessiner
       * @param pos1 les coordonnées du premier point de la ligne
       * @param pos1 les coordonnées du dernier point de la ligne
       * @param color la couleur de la ligne
       */
      void draw_line (RenderWindow& w, Point pos1, Point pos2, Color color);

      /** Affiche un cercle coloré vide
       * @param w une fenêtre ouverte dans laquelle dessiner
       * @param center la position du centre du cercle
       * @param r le rayon du cercle
       * @param color la couleur du trait
       */
      void draw_circle (RenderWindow& w, Point center, int r, Color color);

      /** Affiche un cercle coloré plein 
       * @param w une fenêtre ouverte dans laquelle dessiner
       * @param center la position du centre du cercle
       * @param r le rayon du cercle
       * @param color la couleur du trait et du remplissage
       */
      void draw_filled_circle(RenderWindow& w, Point center, int r, Color color);

  À noter qu'elles prennent la fenêtre où dessiner comme premier
  paramètre (`w`). Le symbole `&` indique que cette fenêtre est passée
  par référence afin que les fonctions puissent la modifier. Vous pouvez
  essentiellement ignorer ce détail technique dont vous verrez les
  tenants et les aboutissants au deuxième semestre.

  Notez aussi les variables de type `Point`. Ces dernières représentent
  des coordonnées. On peut créer un point et accéder à ses coordonnées
  comme suit :

  ```
  Point p = {42, 2713};
  int x = p.x; // 42
  int y = p.y; // 2713
  ```

  Techniquement parlant, il s'agit d'un *enregistrement* (*struct* en
  anglais); vous en verrez les détails au deuxième semestre.

  Dans notre bibliothèque, ces fonctions sont implémentées via des
  appels directs à des fonctions de la `SFML`. Par exemple :

  :::{literalinclude} primitives.cpp
  :start-after: BEGIN draw_filled_circle
  :end-before: END draw_filled_circle
  :::

  1.  Réimplantez ces fonctions, en n'utilisant que des
      appels à `draw_point`.

      % REMPLACEZ CETTE LIGNE PAR VOTRE RÉPONSE

  ::::


id: 814422fa5355467c90d583e2c182e4b3
name: 40
cell_type: markdown
checksum: 09775fae68e86d2b7c93e81b29b3bbb4
notebook_id: 3d4f0337cfb14542bd75470f682b424a
source:
  ::::{admonition} Exercice 4 : Souris et Clavier

  Voici maintenant un fragment de programme interactif utilisant la
  `SFML` et notre bibliothèque `primitives` pour réagir à des actions
  avec la souris ou le clavier.

  :::{literalinclude} exemple-graphisme2.cpp
  :start-after: BEGIN
  :end-before: END
  :caption: exemple-graphisme2.cpp
  :::

  1.  En vous inspirant du programme précédent, écrivez un programme qui
      attend que l'utilisateur clique sur deux points de l'écran puis
      qui trace le segment les reliant.

      % REMPLACEZ CETTE LIGNE PAR VOTRE RÉPONSE

  2.  Écrivez un programme qui attend que l'utilisateur clique sur
      quatre points puis qui dessine le quadrilatère ayant ces quatre
      points comme sommets.

      % REMPLACEZ CETTE LIGNE PAR VOTRE RÉPONSE

  3.  Écrivez un programme qui dessine des polygones de la façon
      suivante : l'utilisateur clique sur des points successifs. À
      chaque clic, le programme relie les deux derniers points. Si
      l'utilisateur clique près du point initial, le polygone se ferme,
      et le programme commence un nouveau polygone.
   
  	% REMPLACEZ CETTE LIGNE PAR VOTRE RÉPONSE

  ::::

  [^1]: <https://www.sfml-dev.org>


