Familiarisation avec les bases d'OCaml

Hello world!

Toute initiation à un langage commence invariablement par saluer le monde, ce premier exercice n'y coupera pas.

Création d'un fichier et compilation

Premiers pas

En utilisant la fonction Printf.printf, écrire l'expression permettant d'afficher Hello world! sur la sortie standard du terminal dans votre fichier hello.ml, puis compilez et exécutez votre programme.

Notes

Argument(s) d'un programme

Vous allez modifier votre programme afin qu'il vous salue. Il faudra, pour cela, qu'il lise le nom que vous donnerez comme argument lors de l'exécution.

Rappel

Les arguments passés sur la ligne de commande sont accessibles grâce à Sys.argv.(i)i est un entier qui fait référence au :

  1. nom du programme ;
  2. premier argument ;
  3. deuxième argument ;
  4. ...

Application

Manipulation d'entiers, de nombres à virgules flottantes et lecture sur l'entrée standard

Rappel

La fonction read_int () attend que l'utilisateur ait entré un entier dans le terminal et renvoie cet entier.

Application

Bibliothèque Random et fonction récursive

Vous allez créer un programme interactif dans lequel vous devrez retrouver un nombre généré aléatoirement.

Le fonctionnement du programme est le suivant :

Rappel

On utilisera deux fonctions de la bibliothèque Random :

Application

Améliorations

Exemple d'affichage

./deviner_nombre
  850
  + (il vous reste 9 tentatives)
  863
  + (il vous reste 8 tentatives)
  870
  - (il vous reste 7 tentatives)
  864
  Bravo ! Vous avez atteint le résultat en 4 tentatives.

Application : associer à une date le jour de la semaine correspondant

Ce programme a pour but de définir, pour une date donnée, le jour de la semaine correspondant.

Pour ce faire, il va falloir définir le nombre de jours qui séparent cette date d'une date référence.

Pour se faire une idée du fonctionnement de l'algorithme permettant de résoudre ce problème, rien de mieux qu'un exemple :

Il faut maintenant calculer le nombre d'années qui sépare 2016 de 1756 et convertir cela en jours, puis le nombre de mois qui séparent décembre de janvier et convertir cela en jour, puis enfin ajouter les jours qui séparent le 31 (nombre de jours en janvier) du 27.

Nous allons créer ce programme étape par étape dans un fichier quel_jour.ml.

Les années

Pour la suite, certaines fonctions contiennent un argument b qui est un booléen correspondant au fait que l'année sur laquelle on travaille est bissextile ou pas.

Les mois

Les jours

Fin

Exemple

./quel_jour
  jour   : 27
  mois   : 1
  année  : 1756
  Ce jour était un mardi.
  jour   :

Casse brique sans briques

On utilisera la bibliothèque Graphics pour réaliser les parties graphiques de ce jeu.

Le cadre

On commence par définir dans un fichier cb.ml les constantes left, right, down et up de type float avec les valeurs 0, 300, 0 et 500 respectivement. Ces valeurs représentent les limites du cadre. Écrire ensuite un programme qui ouvre une fenêtre graphique dont les dimensions correspondent à ces 4 constantes. On pourra utiliser pour cela la fonction int_of_float pour convertir un flottant en entier.

Afin d'obtenir un affichage graphique de qualité, on ajoutera l'appel suivant juste après l'ouverture de la fenêtre graphique:

  Graphics.auto_synchronize false

La balle

La balle est représentée par une paire de nombres flottants qui correspondent à sa position. Elle sera dessinée par un cercle dont le rayon est défini dans par la constante ball.

Ajouter à votre programme la déclaration de la constante ball en fixant une valeur pour le rayon de la balle (5 par exemple). Ensuite, en utilisant la fonction Graphics.fill_circle, écrire une fonction draw_ball : float -> float -> unit qui affiche la balle comme un cercle de couleur noire.

Mouvement de la balle

La direction et la vitesse de la balle sont donnés par un vecteur vitesse. Ce vecteur est représentée par une paire de nombres flottants.

On utilisera la fonction Random.float pour fixer une valeur aléatoire à ce vecteur (comprise dans l'intervalle [0;1]*[0;1]).

Écrire une fonction new_position : (float * float) -> (float * float) -> (float * float) qui, à partir de la position de la balle et de son vecteur vitesse, calcule les nouvelles coordonnées de la balle.

La raquette

La raquette est représentée par un rectangle dont la longueur est définie dans la constante paddle. Cette raquette sera déplacée à l'aide de la souris. La position de la raquette est celle de son point le plus à gauche. L'épaisseur de la raquette est définie à l'aide d'une constante thick.

À l'aide de la fonction Graphics.fill_rect, écrire une fonction draw_paddle : int -> unit tel que draw_paddle x dessine la raquette comme un rectangle noir de longueur paddle (et d'épaisseur 4 par exemple) à la position donnée par la paire (x, down).

À l'aide de la fonction Graphics.mouse_pos, écrire une fonction position_paddle : unit -> int qui, en fonction de la position de la souris, renvoie l'abscisse gauche de la raquette.

Rebonds

Le vecteur vitesse de la balle est modifiée quand celle-ci rebondit sur un bord (gauche ou droit) du cadre, en haut du cadre ou sur la raquette.

Écrire une fonction bounce : (float * float) -> (float * float) -> int -> (float * float) telle que bounce (x, y) (vx, vy) p renvoie le nouveau vecteur vitesse de la balle en fonction de la position (x, y) de la balle, de son vecteur vitesse courant (vx, vy) et de la position de la raquette p.

Boucle principale du jeu

La boucle principale du jeu est réalisée à l'aide d'une fonction récursive game : (float * float) -> (float * float) -> unit qui prend en argument les coordonnées courantes de la balle ainsi que son vecteur vitesse.

L'algorithme de cette fonction consiste à (récursivement):

(1) effacer la fenêtre graphique à l'aide de la fonction Graphics.clear_graph (),

(2) afficher la balle en (x, y) puis synchroniser l'affichage en appelant Graphics.synchronize () ,

(3) tester si la balle est sortie du jeu,

(4) calculer la nouvelle position de la balle (éventuellement après rebond).

Écrire la fonction game et terminer votre programme par un appel à cette fonction (en fixant les coordonnées de départ de la balle).