LIF1 : Algorithmique et programmation impérative, initiation

Transcription

LIF1 : Algorithmique et programmation impérative, initiation
Licence ST
Université Claude Bernard – Lyon 1
LIF1 : Algorithmique et programmation impérative,
initiation
Support de Travaux Pratiques
Elodie DESSEREE
http://perso.univ-lyon1.fr/elodie.desseree/LIF1/index.php
Planning LIF1 - Automne 2014-2015
S1
CM
CM1 : Bases Algo
08/09/2014
CM2 : Bases C
TD
TP
SOUTIEN
TD1 : Bases Algo
TD2 : Algo évolués
S2
15/09/2014
S3
22/09/2014 CM3 : Fonctions / Procédures
S4
S5
29/09/2014 CM4 : Paramètres
06/10/2014 CM5 : Tableaux
TD3 : Fonctions / procédures
TD4 : Passage de paramètres
TP2 : Fonctions / Procédures
S6
13/10/2014
TD5 : Tableaux 1D
TP3 : Paramètres / Tableaux 1D
S7
20/10/2014 CM6 : Chaines de caractères TD6 : Tableaux 2D
S8
27/10/2014
S9
03/11/2014
S10
S11
S12
S13
10/11/2014
17/11/2014 CM7 : Structures
24/11/2014
01/12/2014
S14
08/12/2014 CM8 : Révisions
S15
S16
S17
S18
15/12/2014
22/12/2014
29/12/2014
05/01/2015
TP1 : Bases C
Soutien 1
TP4 : Tableaux 2D
Pas d'enseignements : congés de Toussaint
CC mi-parcours dans la TD Révision 1 (1h30)
séquence d'enseignement TD7 : Chaines de caractères (1)
Pas d'enseignements : 11 novembre
TD8 : Chaines de caractères (2)
TP5 : Chaines de caractères
TD9 : Structures
TP6 : Chaines de caractères
TD10 : Démineur
TP7 : Structures
TD11 : Démineur (suite) + Fichiers
TD Révision 2 (1h30)
TP8 : Démineur
VACANCES DE NOEL
CONTRÔLE TERMINAL - 2h
Soutien 2
Soutien 3
TP 1 : Prise en main de l’environnement / programmes simples
Si aucune erreur de compilation n’est détectée, vous devriez avoir la possibilité d’exécuter
votre programme. Cliquez sur
Objectifs :
prise en main de l’environnement CodeBlocks
apprendre la syntaxe du langage C
traduire des algorithmes
Ce sujet est disponible sur le site de l’UE :
http://perso.univ-lyon1.fr/elodie.desseree/LIF1/index.php rubrique Supports de TP.
1. Connexion sous Windows, Rappel :
Pour l’ouverture d’une session Windows XP :
• Gardez enfoncées les touches <CTRL> et <ALT> puis tapez sur <SUPPR>.
• Dans la fenêtre de connexion, tapez votre nom d’utilisateur (n° d’étudiant dans lequel
le premier chiffre est remplacé par une lettre : 1 par p, 2 par q, etc.),
• puis votre mot de passe (n° BIP sur votre carte d’étudiant),
• puis vérifiez que vous vous connectez sur le domaine « UNIV-LYON1 ».
• Validez (<ENTRÉE>).
2. Créer votre dossier de travail
Pour organiser votre de travail et retrouver facilement vos exercices :
créez un dossier LIF1, un sous-dossier TP1 dans W:
Vous procéderez de même pour chaque TP de ce semestre.
3. Lancement de CodeBlocks
Ce logiciel est un logiciel libre (gratuit) que vous pourrez installer également chez vous pour
terminer les TP.
• Menu Démarrer CodeBlocks.
Si le logiciel n’est pas installé sur votre machine, vous pouvez le télécharger ici :
http://www.codeblocks.org/downloads/26
4. Votre Premier programme pas à pas
Créez un nouveau fichier (Fichier New File …) Sélectionnez Empty C/C++
source puis C++ puis Next. Donnez un nom à ce fichier ayant pour extension .cpp puis
cliquez sur Finish.
Enregistrez votre source C/C++ dans votre répertoire de travail (cf. 2),
avec un nom se terminant par .cpp (important), par exemple : hello.cpp
Recopiez le morceau de code ci-dessous :
#include <iostream>
using namespace std;
int main(void)
{
cout << "Hello !!!" << endl;
return 0;
}
Compilez le programme : Menu Générer, puis Générer (CTRL +F9) ou cliquez sur le
bouton
.
ou bien menu Exécuter, puis Exécuter (CTRL +F10).
Sinon, vous devriez avoir une fenêtre avec le mot « hello », félicitations, votre premier
programme fonctionne correctement !
5. Rédiger un programme à partir d'un algorithme.
Il est relativement simple de "passer" d'un algorithme détaillé à un programme source C/C++.
Voici un résumé des points essentiels sous forme d'exemples et de fragments de source
C/C++.
1. Déclarer une variable :
Un entier correspond à int, réel à float, une valeur logique (vrai, faux) à bool, un
caractère à char…
exemple :
x : réel devient en C
float x;
a : entier devient en C
int a;
remarque : n'oubliez pas le ; à la fin de la ligne.
2. Les instructions élémentaires :
Affecter une valeur à une variable :
a  10
a = 10;
Condition / test / comparer deux valeurs :
Si a < b
opérations à exécuter dans ce cas
Sinon
opérations à exécuter dans l'autre cas (lorsque b <= a)
finSi
remarque : l'égalité entre deux valeurs ou deux variables se note = = en C/C++.
if ( a == b ) /* si a est égal a b */
{
instruction1;
instruction2;
}
else /* a est différent de b */
{
instruction1;
instruction2;
}
Itérations / répéter / tant que :
i0
tant que i <= N
opérations à répéter
i  i +1
fin tant que
c. Écrivez un programme permettant d’afficher un triangle de hauteur N ; N étant demandé à
l’utilisateur et représentant à la fois le nombre maximum d’étoiles sur la dernière ligne et le
nombre de lignes.
Quelle est la hauteur du triangle ?
4
i= 0;
while(i <= N)
{
instruction1;
instruction2;
i= i + 1;
}
Quelle est la hauteur du triangle ?
4
Résultat :
****
***
**
*
Si vous n’avez pas fini cette partie obligatoire du TP pendant la séance,
terminez-le seul !!!
for(i=1;i<N;i++)
{
instruction1;
instruction2;
}
8. Questions subsidiaires (pour les plus rapides)
a. Écrivez un programme qui affiche une ligne de longueur N contentant 1 étoile, N-2
espaces et 1 étoile.
Longueur de la ligne ?
6
6. Exercices pour commencer…
Utilisez vos notes de TD afin de rédiger les programmes suivants :
• Écrire un programme permettant de calculer la moyenne de 3 valeurs réelles
• Écrire un programme permettant d’afficher de la plus petite de deux valeurs
• Traduire en langage C l’exercice 6 du TD1. Programmer une calculatrice proposant les
opérations classiques
• Saisie d’une valeur entre deux bornes
• Écrire un programme permettant d’afficher les tables de multiplication pour tous les
entiers de 1 à 10.
7. Premiers pas, premières étoiles
a. Écrivez un programme permettant d’afficher N étoiles sur une ligne ; N étant demandé à
l’utilisateur.
Résultat :
*
*
(Note : il y a 4 espaces entre les deux étoiles
ici)
b. En utilisant ce que vous venez de faire, écrivez un programme affichant le contour d'un
rectangle de taille N * M.
Longueur du rectangle ?
6
Largeur du rectangle
4
Résultat :
******
*
*
*
*
******
c. Écrivez un programme qui affiche une ligne de longueur n en alternant les espaces et les
étoiles.
Longueur de la ligne
6
Résultat :
* * *
Résultat :
*****
b. Écrivez un programme permettant d’afficher un rectangle de N * M étoiles ; N et M étant
demandés à l’utilisateur.
Quelles sont les dimensions du rectangle : longueur ?
4
Largeur
3
*
**
***
****
d. et maintenant le même triangle à l’envers !!!
Itérations / boucle pour :
Pour i allant de 1 à N par pas de 1 faire
opérations à répéter
fin pour
Combien d’étoiles voulez-vous afficher ?
5
Résultat :
Résultat :
****
****
****
d. En réutilisant ce que vous avez fait, écrivez un programme qui affiche un damier de taille
MxN.
Taille du damier N ?
4
M?
6
Résultat :
* * *
* * *
* * *
* * *
e. Faites en sorte que l'utilisateur puisse afficher un damier en choisissant non seulement sa
taille mais aussi le caractère utilisé.
Résultat :
Quel est la caractère souhaité ?
o
taille du damier N ?
4
M?
6
o o o
o o o
o o o
o o o
f. Essayez d'écrire des programmes permettant d'afficher les figures suivantes...
*
**
***
****
*****
****
***
**
*
*
***
*****
*******
*****
***
*
*
*
*
*********
*
*
*
2. Suite de Fibonacci
LIF 1 – TP 2 : Procédures et Fonctions
Objectifs :
Le but de ce TP est de revoir et manipuler toutes les notions que vous avez
acquises jusqu'à maintenant. A la fin, vous devrez bien maîtriser :
L'importance de la fonction main et la façon d'appeler des procédures et
des fonctions.
Les boucles simples (tant que, faire)
Les boucles imbriquées
La structure conditionnelle (si…alors…sinon)
Les sujets et supports de cours sont disponibles sur le site du cours :
http://perso.univ-lyon1.fr/elodie.desseree/LIF1/index.php rubrique Supports de TP.
1. Reprenez les exercices du TD.
Utilisez vos notes des TD 2 et 3 afin de rédiger les programmes suivants :
•
Fonction permettant de retourner la moyenne de deux réels passés en paramètre.
•
Fonction permettant de calculer et de retourner la factorielle d’un nombre passé en
paramètre. Utilisez ce sous-programme pour afficher les 15 premières valeurs des
factorielles. Comparez les résultats de factorielle (13) et factorielle (14). Ces résultats
vous semblent-ils cohérents et corrects ? Pourquoi ? Modifiez le type de retour de la
fonction factorielle en double au lieu de int et observez les nouvelles valeurs
obtenues.
•
Fonction permettant de calculer la somme des n premières puissances de 2
•
Lire 20 nombres au clavier et afficher le carré des nombres pairs uniquement
•
Trouver une valeur choisie aléatoirement. L’exemple suivant permet de choisir
aléatoirement une valeur comprise entre 0 et 29.
#include <iostream>
using namespace std;
int main (void)
{
int valea;
srand(time(NULL));
valea=rand()% 30;
cout<<"la valeur aleatoire est : "<<valea<<endl;
system("PAUSE");
return 0;
}
Attention : outre la traduction en langage C des algorithmes écrits en TD, vous devrez
également modifier le code pour écrire des fonctions ou des procédures ainsi que le
programme principal permettant de tester ces sous-programmes.
Soit la suite de Fibonacci définie de la manière suivante :
Si n<2 fibonacci(n) = 1
Si n>=2 fibonacci(n)= fibonacci (n-1) + fibonacci (n-2)
Afficher le nième terme de la suite de Fibonacci (n étant passé en paramètre)
3. Triangle de Pascal
Écrivez un programme qui affiche le triangle de Pascal jusqu'à la ligne n. Pour réaliser ce
programme, écrivez dans un premier temps la fonction combinaison (qui utilisera factorielle):
int combinaison(int n, int p)
Rappel :
La fonction du triangle de Pascal à réaliser à pour signature:
void trianglePascal(int n) ;
trianglePascal(5);
1
1
1
1
1
1
1
2 1
3 3 1
4 6 4 1
5 10 10 5 1
4. Dessiner un carré
En utilisant l’algorithme écrit dans le TD 3 (exercice 7) ainsi que les programmes du TP1,
écrivez un programme permettant de dessiner le contour d’un carré en choisissant le caractère
du contour. Cette fois-ci, vous devrez utiliser une procédure comme le suggère l’exemple cidessous :
afficherCarre(10, ‘*’);
**********
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
**********
5. Dessiner un cercle plein
Écrivez une procédure qui affiche un cercle.
procédure cercle(r : donnée Entier)
// r est le rayon du cercle
6. Questions subsidiaires
a) Renverse (Simple boucle mais non vu en TD)
Cette procédure pourra utiliser une procédure annexe aff_ncar qui affichera n fois le caractère
spécifié dans les paramètres.
procedure aff_ncar(n : donnée Entier, car : donnée Caractère)
Aide : pour bien comprendre ce que fait votre programme quand l'affichage n'est pas correct
(donc pour déboguer votre programme) vous pouvez appeler la procédure aff_ncar avec le
caractère '-' à la place des espaces.
Écrivez un programme renverse.cpp qui demande un entier n et affiche n en inversant
l'ordre des chiffres.
Indication : n modulo 10 (n%10 en C) donne le dernier chiffre (celui de droite); La partie
entière de n/10 donne tous les chiffres de gauche (sauf le dernier). Il suffit alors d'itérer. En C,
si vous divisez deux entiers entre eux vous obtenez la partie entière de la division :
int n,i;
afficherCercle(40);
n=125;
i = n/10; /* i prend pour valeur 12 */
// Testez votre fonction sur de grands
rayons
b) Les frises (triple boucle cachée dans un appel de procédure)
Écrivez une procédure qui affiche une frise :
// A partir d'un demi-cercle, il est facile
d'obtenir le cercle complet
procedure afficherFrise(n,l,h : donnée Entier)
// n est le nombre de fois que se repete le motif
// l est la demi longueur d'un motif
// h est la hauteur d'un motif
R
Nous cherchons AB et BC.
A
B
C
RC va correspondre à notre indice de boucle i.
OB est le rayon du cercle
AB+BC = rayon
O
OB² = OC² + BC² <=> BC=sqrt(OB²-OC²)
Exemple :
afficherFrise( 5, 6, 7);
2. Reprise des TD : passage de paramètres
LIF 1 – TP 3 : Passage de paramètres / Tableaux 1D
Objectifs :
Mode de passage des paramètres : données, données/résultats (cas particulier
des tableaux.
Utilisation des tableaux : déclaration, initialisation, remplissage, calcul à partir
de tableaux, …
Programmez les exercices suivants vus en TD (ou CM) :
a) Permutation circulaire
b) Division Euclidienne
c) Nombre de combinaisons (fonction ET procédure)
d) Résolution d’une équation du second degré (dans CM 2)
Écrivez à chaque fois le programme principal permettant de tester vos sous-programmes.
Le sujet est disponible sur le site du cours :
http://perso.univ-lyon1.fr/elodie.desseree/LIF1/index.php rubrique Supports de TP.
3. Entre passage de paramètres et tableaux…
1. Kezako (Compréhension : fonction/procédure, paramètres et appels):
A partir de la fonction écrite en 2.c) écrivez un sous programme permettant de remplir un
tableau contenant la nième ligne du triangle de Pascal.
a) Que fait le programme ci-dessous ? Réfléchissez et écrivez le texte que vous pensez voir
apparaître à l'exécution de ce programme :
#include <iostream.h>
#include <stdlib.h>
void proc_mult(int a, int b, int& ab)
{
cout << "execution de la procedure proc_mult" << endl;
4. Les tableaux à une dimension
a) Écrivez une procédure tabRemplir qui remplit un tableau de taille TAILLE en demandant à
l'utilisateur les valeurs. On définira TAILLE comme une constante au début du programme :
// En ALGO
Constante : TAILLE : Entier = 5
Procédure tabRemplir(T : donnée-résultat Tab[TAILLE] d'Entier)
ab = a*b;
}
int fonc_mult(int a, int b)
{
cout << "execution de la fonction fonc_mult" << endl;
return a*b;
// En C
#include <iostream.h>
const int TAILLE=5;
void tabRemplir( ...
}
b) Écrivez une procédure tabAff qui affiche sur la sortie standard le contenu d'un tableau
d'entiers :
void kezako(int x, int y, int r1, int& r2)
{
proc_mult( x, y, r1);
Proc tabAff(T : donnée tab[TAILLE]) // En ALGO
r2 = fonc_mult(x,y);
cout << "A la fin de kezako r1=" << r1 << " r2=" << r2 <<endl;
}
int main(void)
{
int a, y, res1, res2;
a = 5;
y = 4;
res1 = 0;
res2 = 1;
c) En C, un tableau ne peut avoir une taille variable : sa taille doit être une constante. Pour
pouvoir gérer un tableau de taille quelconque une manière de faire est de définir une grande
valeur pour TAILLE et d'utiliser une valeur tailleT pour indiquer la taille réellement utilisée du
tableau :
cout << "Dans main avant kezako res1=" << res1 << " res2=" << res2
<<endl;
kezako( a, y, res1, res2);
cout << "Dans main apres kezako res1=" << res1 << " res2="<< res2 << endl;
return EXIT_SUCCESS;
// En ALGO
Constante :
TAILLE : Entier = 100
Proc tabAff(T : donnée Tab[TAILLE] d'Entier ; tailleT :donnée Entier)
}
Faites un copier/coller du programme Kezako afin de vérifier si votre idée est correcte. Sinon
demandez une explication à votre encadrant de TP.
// En C
const int TAILLE=100;
void tabAff(int T[TAILLE], int tailleT)
{
...
Modifiez les procédures des questions a) et b) pour prendre en compte cette amélioration.
d) Écrivez une fonction tabSomme qui renvoie la somme de tous les entiers contenus dans un
tableau T
Fonct tabSomme(T : donnée Tab[TAILLE] d'Entier ; tailleT : donnée Entier) : Entier
e) Écrivez une fonction tabRechPosMin qui recherche le plus petit entier d'un tableau T entre
la case debut et la case fin. Cette fonction renvoie directement la position de ce minimum et
renvoie par l'intermédiaire d'un paramètre donnée-résultat la valeur du minimum.
// Renvoie la position du minimum
Fonct tabRechPosMin( T : donnée tab[TAILLE] d'Entier; debut, fin : donnée Entier;
min : donnée-résultat Entier) : Entier
5. Questions subsidiaires
a- écrire un programme permettant de trier un tableau de 15 éléments en utilisant le
principe du tri à bulles.
Principe du tri à bulles :
fonctionne par comparaisons successives de tous les éléments adjacents d’un
tableau
on échange les deux éléments comparés si le premier est supérieur au second
on recommence l’opération tant que tous les éléments ne sont pas triés
Exemple :
f) Écrivez une procédure tabPermute qui permute deux valeurs d'indices a et b d'un tableau T
Proc tabPermute(T : donnée-résultat tab[TAILLE] d'Entier; a,b : Entier)
g) En utilisant les questions e) et f), écrivez une procédure TriMin qui trie les entiers contenus
dans un tableau T.
Indication : rechercher le minimum du tableau entre les cases 0 et tailleT-1, permuter ce
minimum avec la case 0 du tableau puis recommencer avec le sous-tableau allant de la case 1
à la case tailleT-1 ... ainsi de suite jusqu'à ce que la zone de recherche du minimum soit de
taille 1.
h) Écrivez la fonction principale sous forme de menu proposant à l’utilisateur de tester chacun
des sous-programmes écrits précédemment.
b- transformez votre programme de manière à compter le nombre d’affectations
effectuées pour trier ce tableau de 15 éléments. Essayez d’augmenter progressivement
le nombre d’éléments dans le tableau à trier et concluez sur l’efficacité de cet
algorithme de tri.
c- Reprenez la question 4g) et ajoutez un paramètre à cette procédure pour pouvoir
choisir entre un tri par ordre croissant et un tri par ordre décroissant, par exemple avec
un caractère : 'c' pour croissant et 'd' pour décroissant.
d- Écrivez une procédure qui manipule deux tableaux t1 et t2 (de même taille) et qui
modifie t2 en ajoutant à chaque élément de t2 la valeur de l'élément correspondant
dans t1. Par exemple, si t1 = [1 3 5 9] et t2 = [2 4 6 8], alors après l'appel de la
procédure, t1 sera inchangé et on aura t2 = [3 7 11 17]
e- Écrivez une procédure qui effectue la fusion de deux tableaux triés de tailles
quelconques (toujours à l'aide du paramètre tailleT)
Par exemple :
Fusion de t1=[1 3 5 9] et t2=[4 7 11 17] donnera tr=[1 3 4 5 7 9 11 17]
Que fait votre programme si la longueur de t1+t2 est plus grande que TAILLE?
LIF 1 – TP 4 : Tableaux 2D
Objectifs :
Lorsque le débogueur est bloqué (sur un point d’arrêt ou consécutivement à l’emploi de la
commande Executer jusqu’au curseur) on doit le débloquer par une des commandes :
Manipuler des tableaux à deux dimensions
Apprendre à repérer et corriger les erreurs dans un programme
•
•
Le sujet est disponible sur le site du cours :
http://perso.univ-lyon1.fr/elodie.desseree/LIF1/index.php rubrique Supports de TP.
1. Petit exercice pour commencer !!!
a) Soit un tableau d’entiers à deux dimensions de taille maximum TAILLE_LIGNE et
TAILLE_COLONNE. Écrivez une procédure qui, à partir du nombre de lignes et de
colonnes données par l’utilisateur remplit les tailleL * tailleC cellules de ce tableau.
b) Écrivez une procédure qui affiche (proprement) le contenu du tableau précédent.
c) Écrivez enfin les fonctions de calcul de somme sur une ligne et sur une colonne vues
dans le TD6.
// En ALGO
Constante :
TAILLE_LIGNE : Entier = 100
TAILLE_COLONNE : Entier = 100
•
Pas à Pas (Next Step) : exécuter une instruction, en considérant qu’un appel de
fonction est une instruction atomique qu’il n’y a pas lieu de détailler,
Avancer (Step Into) : avancer d’une instruction, en s’arrêtant, le cas échéant, à
l’intérieur des fonctions appelées,
Continuer : relancer l’exécution du programme, jusqu’au prochain point d’arrêt ou,
s’il n’y en a plus, jusqu’à la fin.
Examiner les variables. Pour faire afficher une variable dans le volet Debug à gauche de
l’écran il suffit cliquer sur le bouton Ajout variable ou bien de double-cliquer sur la variable.
En fait, passer (lentement, soyez patients) le curseur sur la variable suffit la plupart du temps
pour l’ajouter au volet Debug. La variable et sa valeur sont ensuite constamment affichées et
on peut en observer l’évolution pendant que le programme est exécuté.
Reprenez le programme Kézako du TP 4 (avant les modifications) et testez le débogueur
dessus. Essayer notamment d’afficher le contenu des variables r1, r2, res1, res2, … Modifiez
le code comme vous l’aviez fait dans le TP3 puis relancez le debogueur.
#include <iostream>
#include <stdlib.h>
using namespace std ;
void proc_mult(int a, int b, int& ab)
Proc tabAff(T : donnée Tab[TAILLE_LIGNE][TAILLE_COLONNE] d'Entier; tailleL,tailleC
: donnée Entier)
{
// En C
const int TAILLE_LIGNE=100;
const int TAILLE_COLONNE=100;
}
cout << "execution de la procedure proc_mult" << endl;
ab = a*b;
int fonc_mult(int a, int b)
{
cout << "execution de la fonction fonc_mult" << endl;
void tabAff(int T[TAILLE_LIGNE][TAILLE_COLONNE], int tailleL, int tailleC)
{...
return a*b;
}
void kezako(int x, int y, int r1, int& r2)
2. Utilisation du débogueur
{
proc_mult( x, y, r1);
Dans cet exercice vous allez apprendre à utiliser le débogueur sur un exemple simple.
r2 = fonc_mult(x,y);
cout << "A la fin de kezako r1=" << r1 << " r2=" << r2 <<endl;
Il a deux manières principales de lancer le débogueur :
•
•
placer un point d’arrêt (breakpoint) puis actionner la commande Debugger
placer le curseur au début d’une instruction puis actionner la commande Executer
jusqu’au curseur
}
int main(void)
{
int a, y, res1, res2;
a = 5;
y = 4;
res2 = 1;
<<endl;
kezako( a, y, res1, res2);
cout << "Dans main apres kezako res1=" << res1 << " res2="<< res2 << endl;
system("PAUSE") ;
return EXIT_SUCCESS;
Un programme ne peut être arrêté que sur des instructions, évitez de mettre des points d’arrêt
sur des lignes constituées de déclarations (des déclarations il ne reste aucune trace après la
compilation).
res1 = 0;
cout << "Dans main avant kezako res1=" << res1 << " res2=" << res2
La manière la plus simple de placer un point d’arrêt consiste à cliquer dans la gouttière (la
marge de gauche). Une marque dans la gouttière indique le point d’arrêt, ainsi qu’un
surlignage de la ligne concernée. D’autre part, une flèche dans la gouttière montre
constamment la ligne sur laquelle l’exécution est arrêtée.
}
3. Des caractères dans des tableaux !!!
Dans cette partie nous allons programmer le jeu du morpion. Pour cela, vous avez besoin
d’une grille 3*3 et de 2 joueurs ayant des pions différents (les croix et les ronds).
X X O
O X X
X O O
Grille avec
gagnant
X O X
O X O
O X X
Grille sans
gagnant
A tour de rôle, chaque joueur positionne un de ses pions sur la grille. Le jeu se finit quand un
joueur a réalisé une ligne, une colonne ou une diagonale avec ses pions (c'est le gagnant) ou
quand la grille est pleine (pas de gagnant).
Commencez d'abord par les deux premières fonctions et testez. Puis continuez avec la
fonction metUnPionSurLaGrille et testez. Et enfin, terminez avec la fonction testeFinJeu qui
est un peu plus complexe.
Écrivez ensuite le programme principal permettant de dérouler la partie. En voici son
algorithme :
Algorithme principal :
Initialisation de la grille à vide
Tant que (pas de gagnant ou pas grille pleine)
Afficher grille
Mettre un pion sur la grille
4. Partie Facultative
La grille est représentée par un tableau à 2 dimensions de caractères dont chaque case
contiendra soit ‘_’, soit ‘O’, soit ’X’.
Pour réaliser l’implémentation de ce jeu, écrivez les sous-programmes suivants :
void initialiseGrille(char grille[3][3])
/* Initialise la grille du morpion à vide (caractère ‘_’)*/
void afficheGrille(char grille[3][3])
/* Affiche la grille du morpion
_ indique case vide, O pion joueur 1 et X pion joueur 2 */
void metUnPionSurLaGrille(char grille[3][3], char &prochain_joueur)
/* Saisie les coordonnées du nouveau pion à mettre sur la grille
Si les coordonnées sont en dehors de la grille ou si la case possède déjà un pion, la saisie est
refusée, un message d'erreur est affiché, et le joueur doit rejouer
*/
Boolean testeFinJeu(char grille[3][3], char prochain_joueur)
/* Teste si l'un des joueurs a gagné (ligne, colonne ou diagonale remplie de pions semblables).
Dans ce cas, affiche un message pour indiquer le joueur qui a gagné.
S'il n'y a pas de gagnant, teste que la grille n'est pas pleine. Si elle est pleine, affiche un
message indiquant qu'aucun des joueurs a gagné
Retourne TRUE si la grille est pleine ou si un joueur a gagné
FALSE sinon
*/
Reprenez le programme du morpion que vous venez d’écrire et essayez de le transformer en
puissance 4 !!!
LIF 1 – TP 5 : Chaînes de caractères
Objectifs :
// En C
int main()
{
char txt[CHMAX];
chLire(txt);
cout<<txt;
return 0;
}
Manipuler les chaînes de caractères
Le sujet est disponible sur le site du cours :
http://perso.univ-lyon1.fr/elodie.desseree/LIF1/index.php rubrique Supports de TP.
1. Rappels
Manipuler les tableaux de caractères.
Rappel : une chaîne de caractères en C est représentée sous forme d'un tableau de caractères.
Le caractère spécial '\0' repère la fin de la chaîne. Ceci permet de ne pas utiliser forcement
tout le tableau. Par exemple, un tableau de 20 caractères peut contenir la chaîne "maison" bien
que celle-ci ne comporte pas 20 caractères :
'm' 'a'
'i'
's'
'o'
'n'
'\0' 't'
'r'
'u'
'c'
'q'
'u'
'i'
't'
'r'
'a'
'i'
'n'
'e'
Les fonctions et procédures manipulant des tableaux de caractères respectent toutes cette
convention! Les vôtres aussi!
Attention :
Pour stocker une chaîne de longueur N, il faut un tableau de longueur N+1 à cause du '\0'
terminal. "maison" correspond à un tableau de caractères de 7 cases : les 6 lettres + le '\0'
'c' signifie le caractère c (=1 caractère) alors que "c" signifie le tableau de caractères (= 2
caractères, le 'c' et le '\0').
Il est possible de comparer deux caractères avec == mais cette opération n'est pas valide avec
les tableaux de caractères (car cette opération n'est pas valide sur les tableaux de toutes
sortes).
Si 'c'=='f' alors ...
// OK
Si "maison"=="voiture" alors...
// Interdit!!
Si "c"=="f" alors ...
// Interdit!!
2. Fonctions classiques sur les chaînes
a) Définissez en C une constante CHMAX contenant la taille maximal des tableaux de
caractères manipulés. Il sera alors possible de stocker des chaînes de longueur CHMAX-1 à
cause du '\0' terminal.
// En algo
Constantes : CHMAX : Entier = 100
// En C
const int CHMAX = 100;
b) Écrivez la procédure chLire qui demande à l'utilisateur le nombre de caractères N que va
comporter la chaîne de caractères puis qui demande à l'utilisateur les N lettres de celle-ci.
Cette procédure ajoutera automatiquement le caractère '\0' en fin de chaîne dans le tableau.
// En algo
Procédure chLire(ch : donnée-résultat Tab[CHMAX] de caractère)
Pour vérifier que votre fonction chLire fonctionne correctement vous pouvez afficher votre
chaîne de caractères avec cout. cout affiche tous les caractères du tableau jusqu'à ce qu'il
rencontre le '\0' indiquant la fin du mot.
Remarque : l'instruction chLire(txt) est assez proche de l'instruction cin>>txt. Seulement,
cin>>txt ne demande pas à l'avance le nombre de lettres à saisir, En effet, la fonction cin
considère que la chaîne est terminée lorsqu'elle rencontre un espace ' ' ou un retour à la ligne
'\n'.
Avec chLire il est donc possible de saisir une chaîne comportant des espaces comme "la
pomme est verte" alors que ceci n'est pas possible directement avec cin>>txt : cin ne lira que
"la". Le reste du texte " pomme est verte" sera gardé en mémoire de l'ordinateur et alimentera
un prochain cin.
b) Écrivez la fonction chLongueur qui détermine la longueur d'un mot stocké dans un tableau
de caractères (sans compter le '\0' terminal). Par exemple, sur le tableau "maison" définit en 1.
la fonctions renverra 6.
// En algo
Fonction chLongueur(ch : donnée Tab[CHMAX] de caractère) : Entier
c) Écrivez la procédure chMiroir qui construit le miroir d'une chaîne de caractères. Attention :
cette procédure n'affiche pas le résultat à l'écran. Par exemple, "maison" donnera "nosiam".
// En algo
Procédure chMiroir(ch : donnée tab[CHMAX] de caractère; chR : donnée-résultat
tab[CHMAX] de caractère)
d) Écrivez la fonction chConcat qui concatène deux tableaux de caractères. Le résultat sera
stocké dans le 1er tableau de caractères. Par exemple, la concaténation des deux chaînes
"rouge " et "vert" donnera "rouge vert".
// En algo
Procédure chConcat(ch1 : donnée-résultat tab[CHMAX] de caractère; ch2 : donnée
tab[CHMAX] de caractère)
e) Écrivez la fonction chCompare qui renvoie vrai si deux chaînes de caractères sont
identiques et faux sinon.
// En algo
Fonction chCompare(ch1, ch2 : donnée tab[CHMAX] de caractère) : booléen
Remarque : il est maintenant possible d'écrire Si chCompare(ch1,ch2) alors ... sinon ...
Rappel, ceci est interdit : Si ch1==ch2 alors ...
3. Fonctions plus élaborées
a) En utilisant chMiroir et chCompare écrivez maintenant très rapidement (en 2 lignes) la
fonction chEstPalindrome qui renvoie vrai si les deux chaînes sont des palindromes et faux
sinon.
b) Écrivez une fonction permettant de compter le nombre d’occurrences d’un caractère donné
dans une chaîne de caractères.
c) Écrivez une fonction booléenne permettant de tester si une chaîne de caractères passée en
paramètre est entièrement constituée de majuscules ou non.
d) Après avoir vérifié que la chaîne passée en paramètre ne comportait que des majuscules,
transformez-la en minuscules.
e) Enlevez toutes les voyelles d'une chaîne donnée en paramètre.
4. Partie facultative
Écrivez la fonction chVerlan qui construit la chaîne ou tous les mots sont inversés (miroir)
mais ou l'ordre des mots reste identique. Par exemple, la chaîne "la pomme est verte" donnera
"al emmop tse etrev".
// En algo
chVerlan(ch : donnée tab[CHMAX] de caractère; chR : donnée-résultat tab[CHMAX] de
caractère)
S’il vous reste encore du temps, programmez le jeu du pendu vu dans le CM6 !
2. Tri de chaînes de caractères
LIF 1 – TP 6 : Tableau de Chaînes de caractères et Tri
Objectifs :
utiliser les chaînes de caractères dans des tableaux
programmer un tri simple : le tri par insertion
Il s’agit ici de faire un tri par insertion afin de simuler le comportement d’un dictionnaire.
Vous allez saisir tous les mots les uns après les autres et les insérer au dictionnaire (un
tableau) en conservant l’ordre alphabétique.
Exemple :
Premier mot : train
train
Le sujet est disponible sur le site du cours :
http://perso.univ-lyon1.fr/elodie.desseree/LIF1/index.php rubrique Supports de TP.
1. Reprise du TD8
Deuxième mot : voiture
train
voiture
Troisième mot : avion
avion
train
voiture
Programmez le jeu de mémo proposé dans le TD8. La correction de ce TD n’est
volontairement pas disponible sur le site.
Rappels : Le jeu "mémo" est un jeu de mémoire qui consiste à retrouver les paires d’images
identiques dans une grille d’images retournées. Ici, les images seront représentées par le mot
qu’elles signifient. La grille sera un tableau 2 dimensions.
1
2
3
4
1
2
3
4
Lion
Lion
Poule
Vache
Chat
Chien
Oie
Tigre
Chat
Vache
Canard
Canard
Poule
Oie
Tigre
Chien
a) Soit TAILLE_GRILLE une constante paire définie en début de programme. Écrire
la déclaration du tableau de taille TAILLE_GRILLE*TAILLE_GRILLE contenant
les chaînes de caractères. TAILLE_GRILLE est pair pour que le nombre de cases
dans la grille soit pair aussi.
b) Écrire une procédure d’initialisation de la grille de jeu avec des "*"
c) Écrire une procédure de remplissage de la grille. Cette procédure devra demander
à l’utilisateur (TAILLE_GRILLE)² / 2 chaînes de caractères qui seront insérées
aléatoirement dans la grille de jeu. Attention de bien vérifier que la grille est vide à
l’endroit sélectionné avant d’insérer le mot.
d) Écrire une procédure demandant au joueur de choisir deux cases et d’afficher le
contenu de ces deux cases. Pour cela les coordonnées des deux cases devront être
passées en paramètres du sous-programme afin d’effectuer des saisies inutiles.
e) Écrire une fonction de vérification du choix de l’utilisateur. Si les deux cases
choisies sont identiques la fonction renverra 0 sinon elle renverra 1.
f) Simuler le jeu à deux joueurs jusqu’à ce que toutes les paires aient été trouvées.
Pour cela vous devrez écrire une procédure permettant d’assurer l’alternance entre
les deux joueurs. Le programme principal devra quant à lui faire jouer
alternativement les deux joueurs et comptabiliser le score de chacun. En fin de
partie il affichera le numéro du joueur gagnant.
Quatrième mot : bateau
avion
bateau
train
voiture
Pour réaliser ce programme vous devrez écrire les sous programmes suivants :
a- initialisation du tableau
b- affichage du tableau
c- recherche de l’indice auquel le mot doit être inséré
d- décalage de tous les mots suivant l’indice d’une case vers la droite
e- insertion du mot dans le tableau
f- le programme principale devra proposé à l’utilisateur de saisir des mots tant qu’il le
souhaite.
3. Questions subsidiaires
Reprenez l’exercice 1 du TP en vérifiant à chaque saisie que les valeurs données par
l’utilisateur sont bien dans la grille.
Puis vérifiez que la case qui souhaite découvrir n’a pas déjà été
LIF 1 – TP 7 : Structures
Procédure imDessineRect(im : donnée-résultat Image; c : donnée Caractère; xmin,
ymin, xmax, ymax : donnée Entier)
Le sujet est disponible sur le site du cours :
http://perso.univ-lyon1.fr/elodie.desseree/LIF1/index.php rubrique Supports de TP.
Remarque : L'image n'est pas initialisée entre chaque dessin. Deux figures tracées à la suite
dans une image vont se superposer.
Objectifs :
Manipuler les structures. Une structure est un type qui permet de regrouper
différents champs dans une seule entité
b) OPTION : Écrivez la procédure imDessineCercle qui dessine un cercle plein dans l'image.
Cette procédure n'affiche pas l'image!
Remarque :
Contrairement aux tableaux, une structure n'est pas passée automatiquement en
donnée-résultat. Pour passer une structure en donnée-résultat il faut le spécifier
explicitement dans le prototype de la procédure (ou fonction), avec le symbole
"&" après le type
// En algorithmique
void truc(struct camion Dcam, struct camion& DRcam)
// Dcam est passé en donnée alors que DRcam est passé en donnée-résultat
void truc(int DRi[10], struct camion DRcam[10])
// DRi est passé en donnée-résultat (car c'est un tableau) et Drcam aussi (car
c'est un tableau)
1. Reprise du TD
Reprenez et implémentez les fonctionnalités du TD9 sur les structures.
2. Représentation des images à l’aide d’une structure
a) Définissez en langage C la structure Image représentant une image de caractères. Voici sa
définition en langage algorithmique :
//En algorithmique
Constantes : DIMMAX : Entier = 100
Structure Image
dimx, dimy : Entier // les dimensions de l'image : dimx<=DIMMAX
im : tableau[DIMMAX][DIMMAX] de caractères
Fin Structure
b) Quelle doit être la signature de la procédure permettant d'initialiser une image im avec le
caractère c ? Écrivez cette procédure.
c) Écrivez la procédure imAff qui efface l'écran et affiche l'image :
// En algorithmique
procédure imAff(im : donnée Image)
Attention : il faut afficher l'image de haut en bas car l'écran se remplit de haut en bas!
Rappel : pour effacer l'écran l'instruction est
system("cls");
3.Partie facultative : Dessin
(boucle avec bornes évoluées)
a) Écrivez la procédure imDessineRect qui dessine un rectangle rempli avec le caractère c
dans l'image. Cette procédure n'affiche pas l'image !
// En algorithmique
Procédure imDessineCercle(im : donnée-résultat Image; c : donnée Caractère; x,y,r :
donnée Entier)
Version simple de l'algorithme : parcourez toutes les case de l'image, si la case considérée à
une distance au centre du cercle inférieure au rayon, la case est dans le cercle.
c) Insérez les procédures de tracé de ligne suivante dans votre programme (si vous avez
respecté les consignes, ceci devrait marcher sans rien changer au reste de votre programme à
part l'algorithme principal) :
// En C
#include <math.h> // Pour sqrt();
void imSet(struct image &im, int x, int y, char c)
{
im.im[x][y] = c;
}
void imDessineLigne(struct image &im, char c, int xi,int yi,int xf,int yf)
{
int x,y ;
float a,b ;
a =(float) (yf-yi)/(xf-xi) ;
b = yi - a * xi ;
for ( x = xi ; x <= xf ; x++ )
{
y = ((int) (a * x + b ));
// calcul l'ordonnee du point
(conversion du float en int)
imSet(im,x,y,c); // allume le pixel (x,y) ;
}
}
void imDessineLigneBresenham(struct image &im, char c, int xi,int yi,int xf,int yf)
{
int dx,dy,cumul,x,y ;
x = xi ;
y = yi ;
dx = xf - xi ;
dy = yf - yi ;
im.im[x][y] = c; // allume le pixel (x,y) ;
cumul = dx / 2 ;
for ( x = xi+1 ; x <= xf ; x++ )
{
cumul += dy ;
if (cumul >= dx)
{
cumul -= dx ;
y += 1 ;
}
imSet(im,x,y,c); // allume le pixel (x,y) ;
}
}
Remarque : Que se passe-t-il si vous dessinez une figure qui dépasse de l'image «à gauche»?
et «à droite»? Comment pourriez-vous éviter facilement ces cas critiques?
Aide : regardez autour de la fonction imSet utilisée pour le dessin d'une ligne.
2- Création de la grille de jeu
LIF1 – TP 8 : Exemple de conception
Le sujet est disponible sur le site du cours :
http://perso.univ-lyon1.fr/elodie.desseree/LIF1/index.php rubrique Supports de TP.
Objectifs :
TP de révision de toutes les notions abordées dans l’UE. Conception d’un jeu.
1. Le démineur
Programmez la version du démineur telle qu’elle vous a été proposée dans le TD10.
2. La bataille navale (partie facultative)
Il s’agit de réaliser un jeu de bataille navale.
Règles du jeu : La bataille navale est un jeu de société dans lequel deux joueurs doivent
placer des bateaux sur une grille tenue secrète et tenter de se les 'torpiller' mutuellement.
Dans cet exercice, on vous demandera dans un premier temps de positionner les bateaux, puis
d’essayer de les retrouver dans la grille du jeu. La grille de jeu une grille 10*10 numérotée de
1 à 10 horizontalement et de A à J verticalement. La flotte du joueur est composée de la
manière suivante :
• 1 porte-avions de 5 cases : bateau 1
• 1 croiseur de 4 cases : bateau 2
• 1 contre-torpilleur de 3 cases : bateau 3
• 1 sous-marin de 3 cases : bateau 4
• 1 torpilleur de 2 cases : bateau 5
Les bateaux peuvent se toucher par le bout ou le côté mais pas se croiser.
En cas d'erreur dans la construction d'un bateau, le jeu recommence.
1. créer la flotte, c'est à dire placer les bateaux sur la grille du jeu
2. jouer :
a. saisir la case à sonder
b. si la case sondée appartient à un des bateaux de la flotte
touché, supprimer la case du bateau
si le bateau ne contient plus de cases, supprimer le bateau de la flotte
s'il n'y a plus de bateau dans la flotte, la partie est gagnée.
La première question à laquelle il faut répondre est : "comment représenter les bateaux ?".
Une fois que la représentation sera choisie, il ne restera plus qu'à écrire les différentes
manipulations nécessaires à la programmation du jeu.
Les deux plus grosses parties du jeu sont la création de la grille et la recherche du bateau
touché. Nous allons décrire ces parties de manière plus précise dans la suite du sujet.
1- Représentation des bateaux
Le choix d'une représentation est toujours délicat, il faut considérer les opérations ou les
manipulations à réaliser sur la représentation afin de choisir la plus adaptée.
Nous allons ici choisir de décrire un bateau par une origine, une orientation et une longueur.
Écrire la ou les structures permettant de décrire un bateau.
La grille de jeu est un tableau 10*10 sur laquelle les différents bateaux sont positionnés. Les
bateaux peuvent être horizontaux ou verticaux mais ne doivent pas se croiser. Le
positionnement sera dans un premier temps effectué par le joueur qui donnera pour chaque
type de bateau son orientation et sa case d’origine.
La grille de jeu contiendra plusieurs valeurs
- 0 : signifiera qu’il n’y a pas de bateau
- 1 à 5 : numéro du bateau
- 8 : case déjà sondée, bateau touché
Outre la grille de jeu qui contiendra toutes les informations relatives au positionnement des
bateaux et aux cases déjà sondées, nous aurons besoin d’afficher à chaque étape au joueur une
autre grille appelée grille_joueur (partielle celle-ci) qui ne donnera que les informations de
contenu sur les cases sondées.
Écrire les structures de données contenant la grille du jeu et la grille affichée au joueur ;
Attention : les éléments de grille_jeu et de grille_joueur ne seront pas de même type !!!
Écrire une procédure d’initialisation de la grille de jeu avec des ‘0’
Écrire une procédure d’initialisation de la grille du joueur avec des ‘–‘
Écrire une procédure d’affichage de la grille de jeu
Écrire une procédure d’affichage de la grille du joueur
Il faut ensuite placer les bateaux sur la grille de jeu en choisissant leur orientation et origine et
en vérifiant à chaque fois que les bateaux ne se croisent pas et que l’on ne sort pas de la grille.
Écrire une fonction creer_bateau qui demandera à l’utilisateur la case origine et
l’orientation du bateau à créer. Cette fonction renverra le bateau ainsi créé.
Écrire une fonction bateau_verifie qui vérifiera avant de créer le bateau que les
informations données par le joueur sont correctes (pas d’intersection de bateaux ni de sortie
de grille). Cette fonction renverra 1 si l’une des cases est déjà occupée par un autre bateau, 2
si le bateau sort de la grille et 0 si le bateau peut être créé.
Écrire une procédure place_bateau qui remplira les cases de la grille de jeu avec le
numéro du bateau.
Écrire une procédure rempli_grille qui positionnera tous les bateaux sur la grille de jeu.
3- Le jeu
Résumons les différentes étapes du jeu :
1. saisir la case à sonder
2. si la case sondée appartient à un des bateaux de la flotte
o touché, supprimer la case du bateau
o si le bateau ne contient plus de cases, supprimer le bateau de la flotte
o s'il n'y a plus de bateau dans la flotte, la partie est gagnée.
Écrire une procédure jouer qui demandera à l’utilisateur les coordonnées de la case à
sonder sous la forme ligne (de A à J) et colonne (de 1 à 10).
Écrire une procédure verifie_grille qui testera la case choisie par l’utilisateur.
Écrire enfin la fonction principale qui permettra jouer à la bataille navale.