2 Diviser pour régner
1. Simulation du tirage du Lotto
1.9 Comment faire faire à un premier niveau (pour la seconde stratégie) ?
Forts de la première analyse menée à son terme (page 65), nous sommes en mesure de préciser la
1.9.1 Structure des données 1.9.1.1 Constantes
Comme précédemment, 2 constantes sont indispensables : forcément, ces constantes sont attachées à la description même de ce qu'est le Lotto et non à l'analyse déjà menée. Je garde donc, avec la même signification que ci-dessus, NNP et NNT.
Je définirai à nouveau le type NumerosPossibles comme l'intervalle des entiers entre 1 et NNP.
1.9.1.2 Tableau nécessaire
?
Quel est ici, pour rendre compte de la seconde manière de procéder, le tableau à définir ? Avec combien de tiroirs et quelles étiquettes ?Pour calquer le "Comment faire faire ?" sur la seconde stratégie développée, il nous faut à présent une étagère à NNP tiroirs. Nous marquerons un numéro (non encore marqué) en changeant le contenu du tiroir portant ce numéro.
L'idéal serait donc de choisir une étagère booléenne (chaque tiroir contenant seulement soit vrai soit faux). Par ailleurs, ceci nous permettra d'approfondir les traitements mettant en oeuvre les booléens.
On peut bien entendu choisir ici un tableau de type entier, caractère, ...Ceci conduit à une structure de solution identique mais à quelques changements d'écritures.
Ainsi donc, une étagère étant nécessaire, je la baptiserai DejaObtenus : quand le tiroir d'étiquette N sera (= contiendra) vrai, c'est que le nombre N aura été "déjà obtenu"; si tiroir est (contient) faux, N n'est pas "déjà obtenu".
DejaObtenus
vrai faux vrai vrai vrai vrai faux faux
1 2 3 4 ... ... 25 26 ... ... NNP
L'étagère DejaObtenus comporte comme étiquettes la suite des NumerosPossibles (entre 1 et NNP). Les NNP tiroirs sont tous de type booléen.
En Pascal : DejaObtenus : array[NumerosPossibles] of boolean.
1.9.2 Marche à suivre
Je vais évidemment la calquer autant que possible sur celle de la première stratégie. Il faut cependant être attentif à trois détails :
- la vérification du fait qu'un tirage a déjà été obtenu est bien plus facile; - le complémentaire est traité à part, tant lors des tirages que lors de l'affichage.
Tout ceci conduit à proposer :
FAIS TOUT CE QU'IL FAUT POUR PRESENTER A L'UTILISATEUR UN ECRAN D'AVERTISSEMENT (CF LES SPÉCIFICATIONS) QUI DEVRA S'EFFACER A LA FRAPPE DE ENTREE.
Répéter
FAIS TOUT CE QU'IL FAUT POUR INITIALISER L'ETAGERE
DejaObtenus EN PLAÇANT faux DANS TOUS LES TIROIRS.
Place vrai dans le tiroir de l'étagère DejaObtenus portant comme numéro un nombre au hasard entre 1 et NNP.
Pour Compteur allant de 2 à pred(NNT)
FAIS TOUT CE QU'IL FAUT POUR MARQUER vrai UN TIROIR AU HASARD DE DejaObtenus ET QUI NE CONTENAIT PAS DEJA VRAI.
Compteur de type
entier
FAIS TOUT CE QU'IL FAUT POUR PLACER DANS
Complementaire UN NOMBRE AU HASARD ENTRE 1 ET NNP
NON ENCORE OBTENU
FAIS TOUT CE QU'IL FAUT POUR AFFICHER LES RESULTATS TELS QUE MARQUES DANS DejaObtenus ET POUR AFFICHER LE Complementaire.
Complementaire de
type NumerosPossibles
Demande à l'utilisateur s'il veut recommencer et place sa réponse dans Reponse.
Reponse de type
caractère jusqu'à ce que Reponse = 'N'
Comme précédemment un Compteur est nécessaire (pour le déroulement de la boucle de remplissage des tiroirs de 2 à pred(NNT); nous le choisissons bien entendu de type entier (et même compris entre 2 et NNT). Une variable Reponse est évidemment indispensable aussi.
Il nous faut aussi un casier Complementaire qui contiendra le numéro complémentaire. Il est de type NumerosPossibles.
Sous forme abrégée, la marche à suivre peut se réécrire : AVERTIR
Répéter
INITIALISER
Place vrai dans le tiroir de l'étagère DejaObtenus portant comme numéro un nombre au hasard entre 1 et NNP.
Pour Compteur allant de 2 à pred(NNT) Compteur de type entier
TIRER_NUMERO
TIRER_COMPLEMENTAIRE Complementaire de type NumerosPossibles
AFFICHER
Demande à l'utilisateur s'il veut recommencer et place sa réponse dans Reponse.
jusqu'à ce que Reponse = 'N' Reponse de type caractère
Comme lors du développement de la première stratégie, cette analyse de premier niveau n'est complète qu'à la condition que nous précisions exactement ce qu'est chacune des actions complexes non encore décortiquées.
Ainsi :
INITIALISER Placer faux dans tous les tiroirs de DejaObtenus → DejaObtenus
cf. plus haut
avec
Avant INITIALISER Après INITIALISER - DejaObtenus (tableau de booléens
d'étiquettes de type NumerosPossibles) avec des tiroirs aux contenus non précisés
- DejaObtenus a tous ses tiroirs faux.
TIRER_NUMERO
DejaObtenus →
(cf. plus haut)
Marquer vrai un tiroir qui contenait faux de l'étagère
DejaObtenus, ce tiroir étant choisi au hasard (les
numéros vont de 1 à NNP).
→ DejaObtenus (cf. plus haut)
avec
Avant TIRER_NUMERO Après TIRER_NUMERO - DejaObtenus (tableau de booléens
d'étiquettes de type NumerosPossibles) avec certains des tiroirs contenant encore faux et au moins un contenant vrai.
- un tiroir supplémentaire de DejaObtenus contient vrai
TIRER_COMPLEMENTAIRE
DejaObtenus →
(cf. plus haut)
Placer dans Complementaire un nombre au hasard entre 1 et NNP et qui soit tel que le tiroir portant ce numéro dans DejaObtenus soit faux.
→Complementaire
de type
NumerosPossibles avec
Avant TIRER_COMPLEMENTAIRE Après TIRER_COMPLEMENTAIRE - DejaObtenus (tableau de booléens
d'étiquettes de type NumerosPossibles) avec des tiroirs contenant encore faux et pred(NNT) tiroirs contenant vrai.
- DejaObtenus inchangé
- Complementaire contenant un numéro non noté vrai dans DejaObtenus
AVERTIR Afficher l'écran - titre (cf. les spécifications - le "Quoi
Faire ?" - générales et faire attendre la frappe de Entrée avant d'effacer).
AFFICHER
DejaObtenus →
(cf. plus haut)
Complementaire →
: NumerosPossibles
Afficher les numéros des tiroirs contenant vrai de
DejaObtenus puis afficher Complementaire.
avec
Avant d'AFFICHER Après AFFICHER - pred(NNT) tiroirs de DejaObtenus sont
vrais
- Complementaire contient un nombre entre 1 et NNP.
- DejaObtenus n'a pas changé - Complementaire non modifié
Plus clairement encore que précédemment, cette écriture des spécifications précises de chacune des mini-actions "complexes" laissées non analysées dans la marche à suivre principale est fastidieuse, tant le "Comment faire faire ?" correspondant est immédiat.
Même dans ces cas simples cependant, il faut se forcer à l'écriture des spécifications. Programmer (au sens large de ce mot), c'est avant tout spécifier. (Cf. le chapitre 1 du volume 1 de "Images pour programmer".).
?
Que pensez-vous de la marche à suivre suivante, les actions complexes étant décrites exactement comme ci-dessus ?AVERTIR Répéter
INITIALISER
Pour Compteur allant de 1 à pred(NNT) TIRER_NUMERO
TIRER_COMPLEMENTAIRE AFFICHER
Demande à l'utilisateur s'il veut recommencer et place sa réponse dans Reponse. jusqu'à ce que Reponse = 'N'