JavaScript - Partie 6. TD : jeu du "Plus ou moins"
Sommaire partie 6
Les consignes
Le jeu
Principe du jeu "Plus ou moins" : l'ordinateur choisit un nombre au hasard, plus petit ou égal à 100.
Le but est de deviner ce nombre. A chaque fois qu'on propose un nombre, on indique si le nombre à deviner est plus petit ou plus grand que celui-ci.
Les consignes
Le jeu se déroule donc ainsi :
- choix d'un nombre aléatoire
- on demande des nombres, et on indique si le nombre à trouver est plus grand ou plus petit que ceux proposés
- quand l'utilisateur a gagné, on affiche le nombre de coups qu'il lui a fallu.
Pour l'instant, on place le code directement dans le code de la page, sans créer de fonction.
Quelques précisions concernant chacune des étapes décrites ci-dessus…
Choix d'un nombre aléatoire
 |
En JS, il n'existe pas de fonction "simple" donnant un nombre entier aléatoire, il faut la créer.
On verra cela d'ici quelques chapitres, comme pour l'instant il nous manque quelques notions, voici la fonction ci-dessous. |
Code : JavaScript
1 function nb_aleatoire(min, max)
2 {
3 var nb = min + (max-min+1)*Math.random();
4 return Math.floor(nb);
5 }
(Pour rappel, une déclaration de fonction se place dans l'en-tête de la page web.)
Cette fonction renvoie un nombre entier choisi aléatoirement entre
min
et
max
(inclus).
Un exemple d'utilisation pour simuler un lancé de dé :
Code : JavaScript
1 var de = nb_aleatoire(1, 6);
2 alert("Vous lancez un dé et obtenez " + de);
Demander des nombres et afficher "Plus" ou "Moins"
La seconde étape consiste à demander des nombres, et à afficher à chaque fois si le nombre à deviner est plus grand (plus) ou plus petit (moins), jusqu'à ce que l'utilisateur ait trouvé le bon nombre.
Au passage, on compte combien il lui faut d'essais avant de gagner.
On ne va utiliser que des
prompt
, pour éviter que l'utilisateur ne clique 50 fois sur "
OK" à chaque partie :
Pour l'instant, on se contente d'ignorer le bouton "
Annuler
".
Fin de la partie
On affiche un message annonçant à l'utilisateur qu'il a gagné, en lui indiquant combien de coups il lui a fallu.
Correction
Avant de donner la correction, expliquons comment procéder pour réaliser ce script.
Par où commencer ?
Structure du script
 |
Première question à se poser :
à quoi va ressembler le script ? |
Ici, pas besoin de créer de fonctions, l'énoncé précise que le code sera placé directement dans le corps de la page.
Reste à savoir quelle structure utiliser.
Vu les étapes, ce sera quelque chose comme ceci :
- une initialisation (principalement la déclaration des variables)
- une boucle (pour demander les valeurs et afficher les messages)
- quelques instructions pour afficher le résultat.
La boucle
Choisir quel type de boucle utiliser.
On peut d'ores et déjà éliminer la boucle
for
: la condition de la boucle ne porte pas sur un compteur, mais sur les nombres qu'on demande à l'utilisateur.
Il nous reste
while
et
do… while
.
 |
Pour rappel, la principale différence entre ces deux boucles vient du fait que l'action est exécutée avant la condition dans le cas de do... while.
Avec while, la condition est d'abord évaluée, et ensuite seulement on exécute l'action. |
Dans notre cas, on va demander un nombre à chaque tour de boucle.
La condition portera justement sur ce nombre (est-ce qu'il est égal au nombre cherché ?).
Il est donc plus judicieux d'utiliser
do… while
, car il faut demander le nombre avant de vérifier la condition.
Les variables
Essayons de recenser les variables que nous allons devoir utiliser.
Ce qu'on peut déjà affirmer, c'est qu'il nous faudra :
- une variable qui contiendra le nombre à deviner : appelons-la
nb
- une variable pour compter le nombre de coups, qu'on appellera
cpt
- une pour enregistrer le nombre saisi par l'utilisateur (il faudra faire des tests dessus), qu'on va appeler
saisie
.
De plus, lorsqu'on demandera un nombre à l'utilisateur, le message à afficher dépendra du nombre qu'il a saisi avant.
On va donc créer une variable, nommée
msg
qui contiendra le message qu'il faudra afficher la prochaine fois qu'on demandera un nombre.
Correction
En plaçant ce code dans le corps de la page :
Code : JavaScript
1 var nb = nb_aleatoire(1, 100);// nb a deviner
2 var cpt = 0;// nb de coups
3 var saisie;
4 var msg = 'Le nombre à deviner est compris entre 1 et 100.';
5
6 do
7 {
8 saisie = prompt (msg);
9 cpt++;
10 // message a afficher au prochain tour :
11 if(saisie > nb)
12 msg = "C'est moins";
13 else
14 msg = "C'est plus";
15 }
16 while(saisie != nb);
17
18 alert("Bravo, tu as gagne en " + cpt + " coups !");
 |
Ne pas oublier de déclarer la fonction nb_aleatoire (donnée plus haut) dans l'en-tête de la page. |
Amélioration 1 : jouer plusieurs fois de suite
But de cette amélioration
Petite présentation
L'amélioration proposée à réaliser va permettre de jouer plusieurs parties à la suite, en affichant, une fois le jeu terminé, le meilleur score.
Définir le vocabulaire pour le jeu :
- le script qu'on a créé nous fait jouer une manche du jeu "Plus ou moins" (en abrégé "PoM").
- On appellera partie plusieurs manches de PoM.
Ce qu'on doit faire
La première modification, va consister à créer une fonction (on va l'appeler PoM_manche
), qui jouera une manche de PoM, et qui renverra le score (au lieu de l'afficher). C'est donc, à peu près, le code déjà réalisé.
Pour plus de possibilités par la suite, on va donner deux paramètres, mini
et maxi
, &agarve; cette fonction, et le nombre qu'il faudra deviner sera compris entre ces deux valeurs (incluses).
Ensuite, on va jouer plusieurs manches, en demandant à la fin de chacune si l'utilisateur souhaite rejouer.
Une fois la partie terminée, on affichera le nombre de manches jouées et le meilleur score.
Réalisation du script
Structure
Le programme aura une structure semblable à la précédente : il sera basé sur une boucle. Cette boucle sera encore une fois
do... while, car la condition ("Rejouer ?") vient après la manche jouée.
Pour les variables, on a :
- une variable
cpt
pour compter le nombre de manches
- une variable
best_score
pour enregistrer le meilleur score (on l'initialisera à 0)
- une variable
score
, qui contiendra le score de la dernière manche (on va devoir le comparer au meilleur score, il faut donc le stocker dans une variable).
Création de la fonction
PoM_manche
Les quelques modifications :
- ne plus appeler
alert
, mais utiliser return
pour renvoyer le nombre de coups
- ne plus utiliser 1 et 100 pour le choix du nombre, mais
mini
et maxi
(penser aussi à modifier le premier message).
Code : JavaScript
1 function PoM_manche(min, max)
2 {
3 var nb = nb_aleatoire(min, max);
4 var cpt = 0;
5 var saisie;
6 var msg = 'Le nombre à deviner est compris entre ' + min + ' et ' + max + '.';
7
8 do
9 {
10 saisie = prompt (msg);
11 cpt++;
12 if(saisie > nb)
13 msg = "C'est moins";
14 else
15 msg = "C'est plus";
16 }
17 while(saisie != nb);
18
19 return cpt;
20 }
Code pour jouer plusieurs parties
Code : JavaScript
1 var cpt = 0; // nb de manches jouees
2 var best_score = 0; // meilleur score
3 var score; // score de la partie en cours
4
5 do
6 {
7 score = PoM_manche(1, 100);
8 cpt++;
9 if(score < best_score == 0)
10 best_score = score;
11 continuer = confirm("Bravo, tu as gagne en " + score + " coups.\nVeux-tu rejouer ?");
12 }
13 while(continuer);
14
15 // affichage du meilleur score
16 alert("Tu as joue " + cpt + " manche(s).\nTon meilleur score est de " + best_score + " coups");
Amélioration 2 : quelques finitions
But de l'amélioration
Il s'agit de corriger certains détails :
- on va créer une fonction,
PoM_partie
, qui jouera une partie de PoM (à partir du code de l'amélioration 1). Elle retournera le meilleur score (en plus de l'afficher).
- On précisera à cette fonction (en argument) les valeurs entre lesquelles choisir le nombre aléatoire.
- n va prendre en compte le bouton "
Annuler
" lorsqu'on demande de saisir un nombre : il arrête la manche en cours, affiche le meilleur score des autres manches, et quitte la partie.
L'avantage des deux premiers points est que l'on pourra lancer le jeu à partir d'un lien sur la page, et qu'on pourra proposer plusieurs niveaux de difficulté (en prenant un nombre compris entre 1 et 250, par exemple).
Réalisation
Manière de procéder
Concernant la création de la fonction, pas de difficulté.
En ce qui concerne le bouton "
Annuler
", il y a plus de choses à dire.
La fonction qui est la première concernée est
PoM_manche
(c'est elle qui demande les nombres). Lorsqu'on cliquera sur "
Annuler
", on va immédiatement renvoyer 0, grâce à
return
.
 |
L'utilisation de return au milieu d'une fonction, tout comme break dans une boucle, est à éviter.
Toutefois, il est estimé qu'elle est justifiée dans ce cas : le but du bouton "Annuler " est d'arrêter immédiatement ce qui se passe, d'où une telle utilisation. |
 |
Une manière de l'éviter est d'utiliser une variable booléenne, comme la variable "continuer " dans l'amélioration 1.
Le code est alors un peu plus "lourd", mais mieux organisé (l'arrêt de la boucle se fait par la condition, et non pas par du code contenu quelque part dans la boucle). |
Pour revenir à notre exercice : la fonction
PoM_manche
va donc renvoyer 0 quand on annule la partie.
Dans ce cas, on ne demande pas à l'utilisateur s'il veut continuer (puisqu'il a annulé), mais on va régler la variable
continuer
à
false
(ce qui aura le même effet que si on lui avait demandé et qu'il avait refusé).
Script
Voici donc la fonction
PoM_manche
:
Code : JavaScript
1 function PoM_manche(min, max)
2 {
3 var nb = nb_aleatoire(min, max); // nb a deviner
4 var cpt = 0; // nb de coups pour le trouver
5 var saisie; // nb tape par le joueur
6 var msg = 'Le nombre à deviner est compris entre ' + min + ' et ' + max + '.';
7
8 do
9 {
10 saisie = prompt (msg);
11
12 // si "Annuler"
13 if(saisie == null)
14 return 0;
15
16 cpt++;
17 if(saisie > nb)
18 msg = "C'est moins";
19 else
20 msg = "C'est plus";
21 }
22 while(saisie != nb);
23
24 return cpt;
25 }
… et
PoM_partie
:
Code : JavaScript
1 function PoM_partie(min, max)
2 {
3 var cpt = 0; // nb de manches jouees
4 var best_score = 0; // meilleur score
5 var score; // score de la partie en cours
6 var continuer;
7
8 do
9 {
10 score = PoM_manche(min, max); // joue la manche
11 if(score)
12 {
13 cpt++;
14 if(score < best_score || best_score == 0)
15 best_score = score;
16 continuer = confirm("Bravo, tu as gagne en " + score + " coups.\nVeux-tu rejouer ?");
17 }
18 else
19 continuer = false;
20 }
21 while(continuer);
22
23 alert("Tu as joue " + cpt + " manche(s).\nTon meilleur score est de " + best_score + " coups");
24 return best_score;
25 }
Code final
Voici le code final de la page.
Il y a donc 3 liens, correspondant à 3 niveaux de difficulté.
Code : XHTML
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
3 <head>
4 <title>TD : Jeu du "plus ou moins"</title>
5 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
6
7
8 <script type="text/javascript">
9 <!--
10
11 function nb_aleatoire(min, max)
12 {
13 var nb = min + (max-min+1)*Math.random();
14 return Math.floor(nb);
15 }
16
17 function PoM_manche(min, max)
18 {
19 var nb = nb_aleatoire(min, max);// nb a deviner
20 var cpt = 0;// nb de coups pour le trouver
21 var saisie;
22 var msg = 'Le nombre a deviner est compris entre ' + min + ' et ' + max + '.';
23
24 do
25 {
26 saisie = prompt(msg);
27
28 // si "Annuler"
29 if(saisie == null)
30 return 0;
31
32 cpt++;
33 if(saisie > nb)
34 msg = "C'est moins";
35 else
36 msg = "C'est plus";
37 }
38 while(saisie != nb);
39
40 return cpt;
41 }
42
43 function PoM_partie(min, max)
44 {
45 var cpt = 0; // nb de manches jouees
46 var best_score = 0; // meilleur score
47 var score; // score de la partie en cours
48 var continuer;
49
50 do
51 {
52 score = PoM_manche(min, max);// joue la manche
53 if(score)
54 {
55 cpt++;
56 if(score < best_score || best_score == 0)
57 best_score = score;
58 continuer = confirm("Bravo, tu as gagne en " + score + " coups.\nVeux-tu rejouer ?");
59 }
60 else
61 continuer = false;
62 }
63 while(continuer);
64
65 alert("Tu as joue " + cpt + " manche(s).\nTon meilleur score est de " + best_score + " coups.");
66 return best_score;
67 }
68
69 //-->
70 </script>
71
72
73 </head>
74 <body>
75
76 <p>
77 <a href="#" onclick="javascript:PoM_partie(1,63)">Niveau Zér0</a><br />
78 <a href="#" onclick="javascript:PoM_partie(1,100)">Niveau Normal</a><br />
79 <a href="#" onclick="javascript:PoM_partie(0,250)">Niveau Geek</a>
80 </p>
81
82 </body>
83 </html>