Corrigé de la séance d'exercices 10, Programmation I
Sciences et Technologies du Vivant, Semestre 1

Exercice 1 - Premier essai

#include <iostream>
using namespace std;

#include <stdlib.h>
#include "swindow.h"

int main(int argc, char ** argv)
{
  const int longueur = 300;
  const int hauteur  = 200;
  const int rayon_max = 50;
  const int nbr_cercles = 20;

  // Initialise le generateur de nombres aleatoires
  srand(time(0));

  SimpleWindow window("cercles", longueur, hauteur);
  window.map();

  // Remplit la fenetre en blanc:
  window.color(1, 1, 1);
  window.fill();

  // Dessine en noir:
  window.color(0, 0, 0);

  for (int i=0; i<nbr_cercles; i++) {
    // Tire les coordonnees et le rayon du cercle aleatoirement
    int x = rand() % longueur;
    int y = rand() % hauteur;
    int rayon = rand() % rayon_max;

    // Dessine un cercle
    window.drawCircle(x, y, rayon);
  }

  window.show();

  getchar();

  return 0;
}

Exercice 2 - Arbre

Il y plusieurs choses à faire pour rendre l'arbre moins régulier. Premièrement, on peut varier l'angle entre les branches. Pour un meilleur résultat, on choisira un angle différent pour chacune des deux nouvelles branches.

Ensuite, on peut faire varier la longueur des nouvelles branches. Ici aussi, il vaut mieux utiliser des coefficients différents pour chacune des nouvelles branches.

Pour obtenir un résultat similaire à la figure d'exemple, il convient de bien choisir l'angle maximum entre les branches, ainsi que les coefficients minimum et maximum de longueur. Il est aussi conseillé d'augmenter le nombre de niveaux de l'arbre.

#include <stdio.h>
#include "swindow.h"

void dessine_arbre(SimpleWindow * window,
                   int x1, int y1, int x2, int y2, int nb_niveaux)
{
  // Dessine en vert si on se trouve au dernier niveau, en noir sinon.
  if (nb_niveaux == 0)
    window->color(0, 1, 0);
  else
    window->color(0, 0, 0);

  window->drawLine(x1, y1, x2, y2);

  if (nb_niveaux > 0) {
    const int angle_max = 50;
    const float ratio_min = 0.5;
    const float ratio_max = 0.8;
    float ratio;

    // Choisit aleatoirement la longueur des prochains segments
    // premiere branche
    ratio = (float(rand()) / RAND_MAX * (ratio_max-ratio_min)) + ratio_min;
    int vx1 = int(ratio * (x2 - x1));
    int vy1 = int(ratio * (y2 - y1));
    // deuxieme branche
    ratio = (float(rand()) / RAND_MAX * (ratio_max-ratio_min)) + ratio_min;
    int vx2 = int(ratio * (x2 - x1));
    int vy2 = int(ratio * (y2 - y1));

    // Choisit l'angle aleatoirement entre 0 et angle_max (et le convertit en radians)
    float angle = (rand() % angle_max) * 3.14159 / 180;
    int xA = int(x2 + cos(angle) * vx1 - sin(angle) * vy1);
    int yA = int(y2 + sin(angle) * vx1 + cos(angle) * vy1);

    // Angle different pour la deuxieme branche
    angle = (rand() % angle_max) * 3.14159 / 180;
    int xB = int(x2 + cos(-angle) * vx2 - sin(-angle) * vy2);
    int yB = int(y2 + sin(-angle) * vx2 + cos(-angle) * vy2);

    dessine_arbre(window, x2, y2, xA, yA, nb_niveaux - 1);
    dessine_arbre(window, x2, y2, xB, yB, nb_niveaux - 1);
  }
}

int main(int argc, char ** argv)
{
  const int longueur = 500;
  const int hauteur  = 500;

  // Initialise le generateur de nombres aleatoires
  srand(time(0));

  SimpleWindow window("arbre", longueur, hauteur);
  window.map();

  // Remplit la fenetre en blanc:
  window.color(1, 1, 1);
  window.fill();

  // Dessine en noir:
  window.color(0, 0, 0);

  // Instructions de dessin:
  dessine_arbre(&window, 250, 450, 250, 350, 10);

  window.show();

  getchar();

  return 0;
}

Exercice 3 - Flocons

#include <stdio.h>
#include "swindow.h"

struct Flocon
{
  int x, y;
};

void init_flocon(Flocon * f, int longueur, int hauteur)
{
  f->x = rand() % longueur;
  f->y = rand() % hauteur;
}

void dessine_flocon(SimpleWindow * window, Flocon * f)
{
  window->drawPoint(f->x, f->y);
}

void avance_flocon(Flocon * f, int hauteur)
{
  // Deplacement vertical entre 0 et 3.
  f->y = f->y + rand() % 4;
  // Deplacement horizontal entre -2 et 2.
  f->x = f->x + (rand() % 5) - 2;

  // Si le flocon est arrive en bas de la fenetre, on le replace au sommet.
  if (f->y >= hauteur)
    f->y = 0;
}

int main(int argc, char ** argv)
{
  const int longueur = 200;
  const int hauteur  = 200;

  const int nb_flocons = 500;

  Flocon flocons[nb_flocons];

  // Initialise le generateur de nombres aleatoires
  srand(time(0));

  SimpleWindow window("neige", longueur, hauteur);
  window.map();

  // Initialisation aleatoire de la position des flocons:
  for(int i = 0; i < nb_flocons; i++)
    init_flocon(flocons + i, longueur, hauteur);

  // boucle infinie pour afficher les flocons
  while (true) {
    // Efface la fenetre en bleu clair:
    window.color(1, 0.5, 0.5);
    window.fill();

    // Dessine en blanc:
    window.color(1, 1, 1);

    for(int i = 0; i < nb_flocons; i++) {
      // Affichage des flocons:
      dessine_flocon(&window, flocons + i);

      // Deplace les flocons:
      avance_flocon(flocons + i, hauteur);
    }

    window.show();

    // attends 20ms
    usleep(20000);
  }

  getchar();

  return 0;
}

Exercice 4 - Soyons créatifs

Ce programme affiche un champ d'étoiles en 2 dimensions:

#include <stdio.h>
#include "swindow.h"

const int longueur = 400;
const int hauteur  = 300;
const int nb_etoiles = 500;
const int vitesse_max = 5;

struct Etoile {
  int x;
  int y;
  int vitesse;
};


void init_etoile(Etoile *etoile, int x, int y, int vitesse) {
  etoile->x = x;
  etoile->y = y;
  etoile->vitesse = vitesse;
}


void deplace_etoile(Etoile *etoile) {
  // Deplacement horizontal
  etoile->x += etoile->vitesse;

  // Si l etoile depasse le bord droit de la fenetre, elle recommence sur la colonne de gauche:
  if (etoile->x >= longueur)
    etoile->x = 0;
}


int main(int argc, char ** argv)
{
  // Tableau d'etoiles
  Etoile etoiles[nb_etoiles];
  int i;

  SimpleWindow window("etoiles", longueur, hauteur);
  window.map();

  // Initialisation aleatoire de la position des etoiles:
  for(i = 0; i < nb_etoiles; i++)
    init_etoile(etoiles + i, rand() % longueur, rand() % hauteur, (rand() % vitesse_max) + 1);
  
  while(true) // Boucle infinie
    {
      // efface l'ecran
      window.color(0, 0, 0);
      window.fill();

      // Dessine en blanc:
      window.color(1, 1, 1);

      // Affichage des etoiles:
      for(i = 0; i < nb_etoiles; i++)
        window.drawPoint(etoiles[i].x, etoiles[i].y);

      // Evolution des etoiles:
      for(i = 0; i < nb_etoiles; i++)
	deplace_etoile(etoiles + i);

      // attends 20000 micro secondes
      usleep(20000);

      // affiche le resultat
      window.show();
    }

  return 0;
}

Le programme suivant affiche un champ d'étoiles en 3 dimensions:

#include <stdio.h>
#include "swindow.h"


struct Etoile3D
{
  int X, Y, Z;
  int v;
};

void projection3D2D(float X, float Y, float Z, float f, int largeur, int hauteur,
		    float * x, float * y)
{
  *x = largeur / 2. + f * X / Z;
  *y = hauteur / 2. + f * Y / Z;
}


int main(int argc, char ** argv)
{
  const int longueur = 400;
  const int hauteur  = 400;
  const int f = 1000;
  const int z_max = 10000;

  const int nb_etoiles = 10000;

  Etoile3D etoiles[nb_etoiles];

  SimpleWindow window("etoiles", longueur, hauteur);
  window.map();

  // Initialisation aleatoire de la position et de la vitesse des etoiles:
  for(int i = 0; i < nb_etoiles; i++) {
    Etoile3D * e = etoiles + i;
    e->X = rand() % longueur - longueur / 2;
    e->Y = rand() % hauteur  - hauteur / 2;
    e->Z = rand() % z_max;
    e->v = rand() % 30 + 1;
  }

  while(true) // Boucle infinie
    {
      window.color(0, 0, 0);
      window.fill();

      // Affichage des etoiles:
      for(int i = 0; i < nb_etoiles; i++)
        {
	  Etoile3D * e = etoiles + i;
	  float g = 1. - e->Z / float(z_max);
          window.color(g, g, g);

	  // Calcul de la projection des etoiles dans le plan 2D de l'ecran
	  float x, y;
	  projection3D2D(e->X, e->Y, e->Z, f, longueur, hauteur, &x, &y);
	  window.drawPoint(int(x), int(y));
        }

      // Evolution des etoiles:
      for(int i = 0; i < nb_etoiles; i++)
        {
	  Etoile3D * e = etoiles + i;

          // Deplacement selon l'axe z (les etoiles se rapprochent de nous
          e->Z = e->Z - e->v;

          // Si l'etoile depasse la coordonnee z = 0, on la replace au loin
          if (e->Z <= 0)
            e->Z = z_max;
        }
      usleep(10000);

      window.show();
    }

  return 0;
}

Exercice 5 - Courbe de Von Koch

#include <stdio.h>
#include "swindow.h"

void vonKoch(SimpleWindow * window,
	     int x1, int y1, int x2, int y2, int profondeur)
{
  if (profondeur == 0) {
    window->drawLine(x1, y1, x2, y2);
  } else {
    
    //
    //                          point B
    //                             /\
    //                            /  \
    //     point (x1, y1)  ______/    \_____  point (x2, y2)
    //
    //                    point A     point C
    //

    int xA = int(x1 + (x2 - x1) / 3.0);
    int yA = int(y1 + (y2 - y1) / 3.0);
    int xC = int(x1 + 2.0 * (x2 - x1) / 3.0);
    int yC = int(y1 + 2.0 * (y2 - y1) / 3.0);

    int vx = xC - xA;
    int vy = yC - yA;
    float angle = -60 * 3.14159 / 180;
    int xB = xA + cos(angle) * vx - sin(angle) * vy;
    int yB = yA + (sin(angle) * vx + cos(angle) * vy);

    vonKoch(window, x1, y1, xA, yA, profondeur - 1);
    vonKoch(window, xA, yA, xB, yB, profondeur - 1);
    vonKoch(window, xB, yB, xC, yC, profondeur - 1);
    vonKoch(window, xC, yC, x2, y2, profondeur - 1);
  }
}

int main()
{
  const int longueur = 300;
  const int hauteur  = 500;

  SimpleWindow window("von Koch", longueur, hauteur);
  window.map();

  // Remplit la fenetre en blanc:
  window.color(1, 1, 1);
  window.fill();

  // Dessine en noir:
  window.color(0, 0, 0);

  // Instructions de dessin:
  for(int i = 0; i < 4; i++) {
    vonKoch(&window, 0,  100 + i * 120, 300, 100 + i * 120, i + 1);
  }

  window.show();

  getchar();

  return 0;
}


Retour