2015-03-01
- correction cosmétique
   du modèle du Blog
  ° diaporama occupant
     tout l'écran
  ° message défilant
     démarrant du bord
     droit sous Chrome

Trognon le chaton

En lumière..

Des articles Lesbiens: Camellia Rose ,
Lipsticks [:* Fanny] , Lisa
et des Histoires signées MyLzz59: Mylène écrit (http://mylene-ecrit.blogspot.fr)

Des articles Trans-*: Ma Vie En Rose ,
Wawa's Smile , FtM ? , Thomas Beatie 2

Des Coups de Coeur: EXL ,
Kashimashi ~Girl meets Girl~ ,
Sa Majesté Freddie , Mon Côté Midinette
des Coups de Gueule: Karol relève-toi ,
BlondeBox , 1 pub 2 mR2 [bon courage :D]
et des Coups de Blues: Pile 1 an ,
Baisser de Rideau , Interlude

Du Visual Basic (VB6-VBA): Mlle Hanoï
Boules , Bombes , AnaClock , DigiClock ,
Tris (tetris) ,
et de la Bricologie: Real Barbie Girl

Pis pour les plus grand(e)s, des
S*X TOYS:
DildoBike , Tech To Nique

Et même parfois de la vraie vie:
Impressions de Voyage (Maroc) ,
Chez Mickey , La Tonnelle ,
Nous Nous Sommes Rencontrées

.

La vraie Taunie ..


... Tu me manques :'(


Notre Taz :*




Clock & Zik..

Idée Cadeau..


Attrape-Mouches

dyke goudou gouine homo homoaffectivité homoaffectivity homosexual homosexualité homosexuality homosexuel homosexuelle inverti invertie lesbian lesbianism lesbianisme lesbien lesbienne lez néovagin neovagina réassignation saphique saphisme sapphic sapphism trans transgender transgenre transidentité transidentity transsexalité transsexality transsexual transsexualism transsexualisme transsexuel transsexuelle tribade tribadisme vaginoplastie ...

Le combat continue..

MyLzz59..

.. @gmail.com

Blog français

Ca va encore mieux en le disant.. Important
## Comment "marche" ce Blog / Comment laisser un Commentaire ##

Et pour finir,
Mylène écrit (http://mylene-ecrit.blogspot.fr)N'oubliez pas de visiter aussi
mon blog d'histoires ====>



-MyLzz59-

mardi 13 octobre 1970

MSG-Mind (P)08/2010 MyLzz59

(Rubrique VB-VBA)

0) Intro

Nouvelle incursion dans le monde de la programmation VB/VBA, avec cette fois une réalisation bien plus simple que les trois précédentes (nan, pas "réunies" ) "Boules", "Bombes", et surtout "Tris (Tetris)".

Déjà ces dernières utilisent comme interface une feuille Excel (pas si répandu que cela chez les particuliers..), de plus (et tout particulièrement "Tris") elles multiplient les appels de procédures dont des événementielles.

Ici, tel un retour aux sources, une seule procédure, de moins de deux écrans (éditeur) de long, lignes de commentaires comprises. En outre, ce code est indépendant de l'application hôte, aussi il fonctionnera quelle que soit celle choisie (Word, Excel, Powerpoint, etc..)

J'en profiterai au passage (à la source ) pour revenir sur quelques notions "ancestrales" de Basic, que j'utilise couramment dans mes codes, et particulièrement ici

1) MasterMind

a] Généralités

Ce jeu de logique fait partie des "classiques" des jeux de société. Il a été inventé dans les années 1960 par l'Israélien Mordecaï Meirowitz, et a été commercialisé en France en 1976 (Hasbro). Il se présente sous la forme d'une boîte trouée et de "punaises" de diverses couleurs.

MasterMind se joue à deux. Le premier joueur (ou la machine ) définit à l'aide des punaises une séquence ordonnée de 4 couleurs (parmi les huit possibles), chaque couleur pouvant figurer zéro, une, ou plusieurs fois dans cette séquence.

Le but de l'autre joueur est de retrouver cette séquence (qu'il ne voit pas), en un nombre de coups limité (dix dans la version originale), en s'appuyant sur les informations recueillies dans les coups précédents.

Ces informations se limitent au nombre de "punaises" bonnes et bien placées, ainsi que bonnes mais mal placées. Exemple:

La séquence à trouver est "Rouge, Rouge, Vert, Bleu".
La séquence proposée est "Bleu, Rouge, Bleu, Rouge".
Une seule couleur est bonne et bien placée, c'est le "Rouge" en deuxième position.
Puis, le "Rouge" en quatrième position est bon mais mal placé, car en premier dans la séquence à trouver. Idem pour le "Bleu" en première position.
Donc, la séquence proposée contient 1 bien placé et 2 mal placés.

b] Ma version

Elle est volontairement minimaliste. Pas de graphiques, pas d'animations. Juste des MessageBox et InputBox, pas d'autre interface.



Les couleurs des billes sont remplacées par les chiffres de 1 à 8.

Il n'y a pas d'événement de lancement, mais rien ne vous interdit de le rajouter Sinon, pour démarrer le Jeu, cherchez la fenêtre "Macros" ("Menu Outils > Macros > Exécuter une Macro", ou "Onglets Afficher ou Développeur, bouton Macros", ou au clavier: Alt-F8). Sélectionnez la ligne "Msg_Mind", et cliquez Exécuter (ou double-clic sur cette ligne).

2) Rappels sur les MessageBox et InputBox

Ces objets sont des fenêtres pop-up couramment utilisées dans la quasi-totalité des programmes sous Windows. Elles permettent de solliciter l'utilisateur/trice pour lui demander soit de répondre à des choix simples (Oui/Non, Réessayer/Annuler, etc..) soit de renseigner une zone de texte.

Dans Visual Basic, MsgBox et InputBox sont aussi des Fonctions qui renvoient la réponse saisie. Si vous ne voyez pas ce qu'est une fonction, prenons l'exemple d'un cosinus. On lui fournit un paramètre qui est l'angle, et cosinus renvoie la valeur du ..cosinus de cet angle En VB, on récupèrerait dans la variable C le cosinus de l'angle A ainsi: C=COS(A)
C est la valeur retournée par la Fonction COS() et A le Paramètre passé à la Fonction.

L'appel de MsgBox() ou InputBox() (les fonctions) "interrompt" Visual Basic, fait apparaître la Fenêtre pop-up correspondante, et l'exécution du programme ne reprendra que lorsque cette Fenêtre aura été validée. La Fonction renverra alors ce que l'utilisateur/trice aura validé.

a] MessageBox (MsgBox)


La syntaxe typique de la Fonction MsgBox() est la suivante:

V=MsgBox(Prompt$,Options,Titre$)
Où Prompt$ et Titre$ sont respectivement les chaînes texte du message à afficher, et du titre du MessageBox. Prompt$ est le SEUL paramètre obligatoire, tous les autres peuvent être omis. Notez également que Prompt$ est multiligne, l'insertion d'un saut de ligne s'obtient par l'ajout de la constante VbCrLf (=Chr$(13)+Chr$(10)):
"Première Ligne"+VbCrLf+"Seconde Ligne"

Options est une valeur numérique entière résultant de l'addition (binaire) de plusieurs valeurs numériques représentant chacune l'une des options distinctes du MessageBox: choix d'une Icône, Choix des Boutons proposés, Choix du Bouton par défaut, etc..

Options omis affiche un MsgBox sans icône, et avec pour seul bouton "OK". Dans ce cas, peu importe la valeur retournée par MsgBox(), donc l'on peut remplacer "V=" par "CALL", soit même écrire MsgBox() comme une Procédure et non une Fonction: MsgBox Prompt$


MsgBox() offre un choix de quatre Icônes prédéfinies. A chacune est associée un multiple de 16, associé à l'une des Constantes Intrinsèques suivantes:

vbCritical ( = 16 = 16 x 1 )
vbQuestion ( = 32 = 16 X 2 )
vbExclamation ( = 48 = 16 x 3 )
vbInformation ( = 64 = 16 x 4 )


MsgBox() dispose de 6 Jeux de Boutons prédéfinis, celui par défaut est le Bouton "OK" seul. A chaque Jeu correspond une Constant Intrinsèque de valeur multiple de ..1:

vbOKOnly ( = 0 )
vbOKCancel ( = 1 )
vbAbortRetryIgnore ( = 2 )
vbYesNoCancel ( = 3 )
vbYesNo ( = 4 )
vbRetryCancel ( = 5 )

Sans précision, c'est le premier Bouton (celui le plus à gauche) qui est sélectionné par défaut. MsgBox() possède quatre Constantes Intrinsèques permettant de définir lequel des Boutons sera le défaut, multiples de 256:

vbDefaultButton1 ( = 0 = 0 x 256 ) le plus à gauche
vbDefaultButton2 ( = 256 = 1 x 256 )
vbDefaultButton3 ( = 512 = 2 x 256 )
vbDefaultButton4 ( = 768 = 3 x 256 ) le plus à droite

Mais quel est ce mystérieux quatrième bouton, alors que tous les choix n'en comportent que de un à trois maximum ? Il s'agit d'un bouton "Aide", affichable en ajoutant la Constante Intrinsèque vbMsgBoxHelpButton ( = 16384 ), et associable à un Contexte (une page) d'un Fichier d'Aide. Je ne développerai pas cela ici..


Je ne parlerai pas non plus des autres Constantes d'Options.

Par contre, voyons comment MsgBox renvoie sa réponse: à chaque Bouton affiché correspond une valeur unique entre 1 et 7, et une Constante Intrinsèque.

[OK] : vbOK = 1
[Annuler] : vbCancel = 2
[Abandonner] : vbAbort = 3
[Réessayer] : vbRetry = 4
[Ignorer] : vbIgnore = 5
[Oui] : vbYes = 6
[Non] : vbNo = 7

Rem: notez que la croix en haut à droite de la MessageBox, et donc la touche Echap, correspondent à [Annuler], et ne sont fonctionnelles que si ce Bouton est présent dans les choix, SAUF pour vbOKOnly où elles correspondent à [OK].

b] InputBox

La syntaxe typique de de la Fonction InputBox() est la suivante:
Texte$=InputBox(Prompt$,Titre$, Defaut$)
où Prompt$ et Titre$ fonctionnent comme dans MsgBox().

Defaut$ est le Texte déjà renseigné dans la zone de saisie au démarrage de l'InputBox, ou vide si Defaut$ (optionnel) est omis.


Texte$ contient ce que l'utilisateur/trice a saisi, si il/elle clique sur [OK] ou presse la touche Entrée.

Attention: Si l'InputBox est annulée ([Annuler] ou la touche Echap), Texte$ contient une chaîne vide, et aucune erreur n'est générée. Aussi, il n'existe pas de moyen permettant de différencier l'annulation de l'InputBox de la saisie volontaire d'un champ vide !!

3) Le Diagramme

Petite nouveauté, comme ce programme est relativement simple, voyons un synoptique d'ensemble de son fonctionnement, de sa logique. Certes, il n'est pas "académique" dans la mesure où il ne respecte pas les normes de dessin inhérentes.. (m'en fous )


Ce jeu démarre à "Départ", et finit à "Fin". Entre deux, un enchaînement d'étapes, dont certaines sur lesquelles on reboucle en fonction des situations. Détaillons:

a] Départ

On définit trois constantes: Nom (le Nom de ce Jeu), Tit (le Titre des Fenêtres MsgBox et InputBox), et CM le Nombre de Coups Maximum avant de déclarer la Partie "Perdue".

Puis on affiche un MsgBox avec une petite notice explicative, et une question à deux choix possibles: [Oui]:Jouer, [NON]:Quitter.


[Oui] (par défaut) enchaîne sur le bloc "b] Tirage", et [Non] sur "J] Fin".
Const Nom = "MSG-Mind", Tit = Nom + " (P)08/2010 MyLzz59"
Const CM = 20 ' Nb Coups Maxi
' Question Initiale
If MsgBox("Bienvenue dans " + Nom + vbCrLf + vbCrLf _
+ "Le but consiste à retrouver une séquence" + vbCrLf _
+ "aléatoire de 4 chiffres entre 1 et 8 avec" + vbCrLf _
+ "pour seules indications le nombre de chiffres" + vbCrLf _
+ "bien ou mal placés, en " + CStr(CM) + " coups maximum." + vbCrLf _
+ "Ce jeu fonctionne entièrement en boîtes de dialogue.." + vbCrLf _
+ vbCrLf + " [Oui]:Jouer, [Non]:Quitter" _
, vbExclamation + vbYesNo, Tit) <> vbYes Then GoTo L_Bye

Remarque: ne criez pas au sacrilège et n'allumez pas de bûcher face à l'avant-dernier mot de ce code, j'en parlerai plus loin

b] Tirage

La Chaîne Texte M$ sert à mémoriser les Coups précédemment joués, afin de les afficher pour mémoire lors de la saisie suivante. La variable numérique C est le numéro du Coup en cours d'être joué. Z0$ est la Chaîne Texte dans laquelle est stockée la Séquence à trouver.

Nous commençons par réinitialiser ces trois éléments: M$ à vide, C à 1er Coup, et Z0$ pour l'instant à vide aussi.

Ensuite, utilisons le générateur (pseudo-)aléatoire pour tirer quatre chiffres entre 1 et 8, que l'on concatène (en Texte) dans Z0$.
M$ = "": C = 1: Z0$ = "": Randomize Timer
For T = 1 To 4: Z0$ = Z0$ + CStr(1 + Int(Rnd * 8)): Next T

c] Saisie d'une Séquence


Un simple InputBox qui récapitule les Coups précédents (M$) et demande de jouer le C-ième.. Le stockage a lieu dans Z$.
Z$ = InputBox("Coups joués précédemment :" + vbCrLf + vbCrLf _
+ M$ + vbCrLf + "Coup n° " + CStr(C) + " :", Tit)

d] Vérification: Saisie annulée ?

On ne cherche pas à différencier l'appui de [Annuler] de la saisie d'une Chaîne vide. Si Z$ ne contient rien (dans ces deux cas, donc) on poursuit par l'affichage d'un MsgBox "Vous avez annulé.."


Je détaillerai ce MsgBox dans le bloc "i] MessageBox Question"
If Z$ = "" Then B = True: Q$ = "Vous avez annulé la Saisie..": GoTo L_Question

e] Vérification: Saisie Valide ?

L'idée est de prélever les 4 premiers caractères autres qu'espaces dans la saisie Z$, et de tester s'ils sont parmi les caractères "1" à "8". On positionne une variable "drapeau" (B) à True, et tout caractère invalide la "fait tomber" à False.


Si False, la Séquence saisie est invalide, on l'affiche dans un MsgBox et on reboucle sur le bloc "c] Saisie d'une Séquence"
B = True: Z$ = Left$(Trim$(Z$) + "    ", 4)
For T = 1 To 4: B = IIf(InStr("12345678", Mid$(Z$, T, 1)), B, False): Next T
If B = False Then
MsgBox """" + Z$ + """ n'est pas valide.", vbExclamation, Tit: GoTo L_Saisie
End If

f] Vérification: Séquence déjà Jouée ?

Dernier test de validité, la séquence saisie (au contenu valide) a-t-elle été déjà jouée ? La technique est simple: la Chaîne Texte M$ contient l'Historique des Coups Joués. Il suffit de chercher dans celle-ci la Séquence.


Si trouvée, on l'affiche dans un MsgBox et on reboucle sur le bloc "c] Saisie d'une Séquence"
If InStr(M$, ": " + Z$ + " =") Then
MsgBox """" + Z$ + """ a déjà été joué.", vbExclamation, Tit: GoTo L_Saisie
End If

g] Test: Gagné ?

Avant-dernier test, la Séquence validée est-elle la bonne ? On ne va évidemment pas se contenter de regarder si les séquences Tirée (Z0$) et Saisie (Z$) sont égales


En fait, on va alimenter successivement deux Compteurs, BP et MP, respectivement de Chiffres Bien et Mal Placés, initialisés à zéro.

On commence par faire une copie de ces deux Séquences (Z$ dans Z1$, et Z0$ dans Z2$) car on va avoir besoin de "dégrader" leur contenu pour éviter de comptabiliser plusieurs fois une même information, vulgairement "ôter les punaises" déjà comptées, en leur substituant un caractère différent dans chaque Chaîne ("*" dans Z1$, "@" dans Z2$, par exemple).
Z1$ = Z$: Z2$ = Z0$: BP = 0: MP = 0

Les Bien Placés: on compare position à position les Caractères. S'ils sont identiques, on incrémente BP et surtout on "ôte" par substitution les Chiffres en cette position.
For T = 1 To 4
If Mid$(Z1$, T, 1) = Mid$(Z2$, T, 1) Then
Mid$(Z1$, T, 1) = "*": Mid$(Z2$, T, 1) = "@": BP = BP + 1
End If
Next T

Les Mal Placés: maintenant que l'on a "ôté" les Chiffres Bien Placés, on va utiliser la même technique que pour les Bien Placés, à ceci près que pour chacune des positions de la première Chaîne, on va scanner toutes les positions de la seconde. Dès qu'une concordance est trouvée, surtout on ôte les Chiffres concernés.
For T = 1 To 4
For T2 = 1 To 4
If Mid$(Z1$, T, 1) = Mid$(Z2$, T2, 1) Then
Mid$(Z1$, T, 1) = "*": Mid$(Z2$, T2, 1) = "@": MP = MP + 1
End If
Next T2
Next T

La partie est gagnée si le compteur BP a atteint son maximum, à savoir quatre. Dans ce cas, on poursuit par l'affichage d'un MsgBox "Bravo c'est Gagné" (cf. bloc "i] MessageBox Question")

h] Test: Perdu ?

Après avoir vérifié que le Coup est valide mais pas gagnant, comparons le Compteur de Coups Joués (C), incrémenté de 1, à la Constante CM, nombre de Coups Maximum. Si dépassée, la partie est perdue, on poursuit par l'affichage d'un MsgBox "Perdu, il fallait trouver.." (cf. bloc "i] MessageBox Question")


Dans le cas contraire la partie continue avec une nouvelle demande de Saisie, bloc "c] Saisie d'une Séquence"
C = C + 1
If C > CM Then B = False: Q$ = M$ + vbCrLf + "Perdu, il fallait trouver """ _
+ Z0$ + """": GoTo L_Question
GoTo L_Saisie

i] MessageBox Question

Si vous êtes observateur/trice, vous n'avez pas pu louper la grande similarité entre les trois MsgBox Annulé, Gagné, et Perdu

Dans ces trois messages, au moins les deux premiers choix de ces trois sont présents:
[Oui]: démarrer une Nouvelle Partie => on reboucle sur le bloc "b] Tirage"
[Non]: quitter le Jeu => on reboucle sur le bloc "j] Fin"
[Annuler]: retour à l'InputBox de Saisie => bloc "c] Saisie d'une Séquence"

L'on met simplement en paramètres le Message à afficher (dans Q$), et B à True ou False selon que l'on souhaite ou non gérer le Bouton [Annuler]..

La réponse du MsgBox est directement passée à un Select Case.
Select Case MsgBox(Q$ + vbCrLf + vbCrLf _
+ "[Oui]: Recommencer une Nouvelle Partie" + vbCrLf _
+ "[Non]: Quitter " + Nom + vbCrLf _
+ IIf(B, "[Annuler]: Revenir à la Saisie" + vbCrLf, "") _
, IIf(B, vbYesNoCancel, vbYesNo) + vbDefaultButton3 + vbInformation, Tit)
Case vbYes ' Rejouer
GoTo L_Tirage
Case vbNo ' Quitter
Case Else ' Annuler
GoTo L_Saisie
End Select

j] Fin


Un MsgBox affiche "Bye.." et le code s'arrête..
MsgBox "Bye..", vbInformation, Tit

4) Quoi mon Goto ?

"Vous avez osé ?", Ben oui, j'ai "zosé", comme disait dans l'un de ses sketches l'humoriste Champi (là y'en a qui vont se creuser pour trouver )

Mais pourquoi cette instruction héritée des temps préhistoriques immémoriaux ancestraux où l'on programmait avec des silex sur des antiquités pièces de musées dinosaures machines aux performances ridicules grotesques improbables inexistantes sans commune mesure avec nos joujoux multi-coeurs actuels fait-elle encore de nos jours si peur aux soi-disant "vrais" programmeurs, qu'ils fuient, dénigrent, voire veulent faire exorciser toute personne qui "oserait" se hasarder à seulement penser à envisager de l'utiliser ???

Et ne me faîtes pas le coup du "J'étais pas né(e)"

a] B.A.S.I.C.

Le "langage de macros" (sic) qui équipe Microsoft Office jusque dans sa dernière version en date (ainsi que d'autres produits ayant "acheté" la licence comme Crystal Reports, mais PAS OpenOffice de Sun), aussi (et mieux) désigné par son acronyme VBA, (Visual Basic pour Applications), est en fait l'un des deux "ersatz" descendant directement de Visual Basic version 6.3 (avec VBS, Visual Basic Scripting), le dernier des Mohicans VB (Visual Basic) avant l'apparition de la plate-forme .net (Dot Net, produit concurrent de Sun Java), version datant de ..2001

Je ne m'attarderai pas sur .net ici.. Visual Basic (donc versions 1 à 6) est à voir comme l'évolution "naturelle" de MS-Dos vers Windows de Basic, avec "tout un tas" de nouveaux concepts propres à l'environnement Windows. Notez que Visual Basic n'est PAS un langage réellement orienté objet, mais un langage "qui sait faire" de l'objet

Le parent sous MS-Dos de Visual Basic était QuickBasic, lui-même successeur de GW-Basic. QB disposait déjà d'un éditeur avec des menus, du multi-fenêtre, etc.. alors que GW se résumait très vulgairement à un curseur gris clignotant sur un fond noir



Rembobinons encore. B.A.S.I.C. est né en 1963 et a pour parents John George KEMENY et Thomas Eugene KURTZ. L'idée était de créer un langage généraliste facile d'abord, permettant à des débutants en informatique (à l'époque sur systèmes centralisés (mainframes)) une initiation "en douceur".

B.A.S.I.C. est un acronyme, celui de "Beginners' All-purpose Symbolic Instruction Code". Langage généraliste pour débutants.. Généraliste, Basic l'est, contrairement à d'autres langages "spécialisés" (comme le Cobol) il n'excelle en rien mais est capable de s'aventurer sur énormément de terrains. Pour débutants, Basic n'a cessé de l'être, et même si aujourd'hui il est devenu un "vrai grand" langage, faire ses premiers pas en Basic reste nettement plus facile qu'en bien d'autres langages (la "trousse minimale"). Certes, ça ne dure pas, la programmation de plus haut vol en Basic requiert le même investissement que pour les autres..

Arrêtons-nous sur le phénomène informatique des années 80, l'ère des micro-ordinateurs personnels dits "familiaux". En 1981, Clive Sinclair (anobli depuis) lance une machine étonnante, le premier "ordinateur" abordable pour les particuliers. Dans une petite boîte en plastique noir munie d'un clavier plus que rudimentaire collé sur le dessus et qui se branche sur un téléviseur noir et blanc, il crée autout d'un processeur Zilog Z80A LA machine qui allait lancer un engouement pour l'informatique familiale, lequel prendra fin près d'une décennie plus tard, avec l'arrivée des semi-pro Atari 520 et Commodore Amiga, ainsi que la baisse (relative) du prix des PC réservés aux entreprises jusque là. Dans les pas du Sinclair ZX81, cette décennie a vu fleurir une foultitude de machines familiales où les innovations "géniales" côtoyaient le grand n'importe quoi (nan, pas de marques )

La quasi totalité de ces machines familiales avait pour point commun d'intégrer un BASIC comme langage de programmation, le langage le plus approprié à s'accommoder de si peu de performances.. Mais en fait, l'on devrait plutôt parler DES Basic, non d'UN Basic. En effet, les créateurs de B.A.S.I.C. afin de le populariser l'ont souhaité ouvert, et d'entrée dans le domaine public, et en dehors d'un "noyau" commun d'instructions (LET, IF, GOTO, PRINT..) (et encore ) chaque constructeur a "brodé" son jeu d'instructions complémentaires propres à tirer parti des "spécificités" de sa machine. Bonjour la compatibilité entre machines !

Notez que les premiers PC avaient eux aussi leur Basic intégré, Basica (version primitive de GW-Basic) directement en ROM

b] Numéros de Lignes et Etiquettes

Basic a hérité d'une numérotation systématique de chacune de ses lignes de code, à cause d'un ancien système de sauvegarde aujourd'hui totalement obsolète: les cartes perforées. Peut-être en avez-vous déjà rencontré, si vous avez passé l'épreuve du Code du permis de conduire pas trop récemment Vi vi, le truc qu'il fallait trouer

Il fut une époque où, pour charger un programme dans la mémoire d'un ordinateur, ou pour consulter des données, on ne dégainait pas de clé usb ni de disque dur, mais des cartes perforées. Sur chacune étaient "écrites" quelques lignes de code, et les cartes étaient introduites une à une dans le lecteur. Solution 1: pas de numérotation, et il faut impérativement respecter l'ordre des cartes au risque que le programme n'ait plus aucun sens. Autre difficulté, comment insérer ou corriger des lignes de code, à part reperforer toutes les cartes depuis celle portant la correction jusqu'à la dernière ? Solution 2: numéroter les lignes de code. Ainsi les cartes peuvent être introduites dans n'importe quel ordre, c'est la machine qui reconstitue le code. De plus, des cartes correctives indépendantes peuvent être introduites après, chaque ligne remplaçant alors la ligne de même numéro précédemment acquise..

Basic a donc hérité de cette numérotation des lignes, qu'il a gardée bien après les cartes perforées. Peu importe leur ordre de saisie, elles sont reclassées par numérotation croissante. Il était conseillé de laisser des "trous" dans celle-ci, afin de garder la possibilité d'insérer du code correctif. La commande LIST L1-L2 permettait de réafficher un bloc de lignes de numéros compris entre les deux bornes L1 et L2, et EDIT L3 de rappeler pour modification la ligne L3.

Les Basic des "familiaux" des années 80, Basica, et GW-Basic ont fonctionné sur ce principe. QuickBasic a remplacé la linéarité du code par des appels de procédures nommées (les Sub et Function). Il a également remplacé les numéros de lignes par des étiquettes, lesquelles pouvaient être numériques (raison de compatibilité), alphanumériques, et même supprimées. Attention cependant, QB ne reclassait plus les étiquettes numériques par ordre croissant !

En QB, puis VB, n'avaient à être étiquetées (et non numérotées) que les lignes auxquelles on voulait se référer, via GOTO ou GOSUB.

c] Goto et Gosub

Je fais partie des irréductibles anciens gens qui pensent que sans Goto ni Gosub, un Basic n'est plus vraiment un Basic
GOTO L4
Cette instruction toujours vivante (gna-gna-gna ) en VBA a pour effet d'interrompre définitivement l'exécution d'un code en forçant celui-ci à poursuivre à la première instruction suivant l'étiquette L4 (débranchement). Exemple:
MsgBox "Bonjour"
GoTo Ici
MsgBox "Vous ne me verrez jamais"
Ici:
Msgbox "Au revoir"
Le MessageBox "Vous ne me verrez jamais" n'apparaîtra jamais :)
GOSUB L5
Cette instruction permet un débranchement avec retour vers une sous-procédure interne. Voici la structure typique en VB d'un Gosub:
SUB MonSub (Paramètres divers)
instructions..
GoSub SousSub1
instructions..
EXIT MonSub
SousSub1:
instructions..
RETURN
END SUB
Les instructions se déroulent jusqu'au Gosub (qui peut très bien, comme le Goto, figurer seul, ou dans un test, genre IF). Puis Gosub fait poursuivre par l'exécution des instructions situées après l'étiquette précisée (SousSub1:)

L'instruction de fin d'un sous-sub est RETURN. Dès que Basic rencontre Return, il repart à l'instruction située juste après Gosub. Gosub-Return est donc l'ancêtre des appels de procédures nommées.

Notez la présence d'un EXIT séparant le "Sub principal" de son/ses sous-subs !

Aucun passage de paramètres n'existe dans les Gosub, car comme ils sont inclus dans la procédure "principale", ils partagent la visibilité de l'ensemble de sa portée.

Notez également que si Gosub est à l'intérieur d'un bloc With, le sous-sub ne l'est pas !

d] Mais alors, pourquoi.. ??

L'emploi irraisonné de Goto partant en tous sens rend la compréhension d'un code (même court) aussi facile que si vous essayiez de suivre d'une extrémité à l'autre un spaghetto dans un plat de spaghetti Ces codes en portent d'ailleurs le nom: codes spaghetti

Professionnellement, un programme doit être lisible non pas seulement par vous si vous en êtes l'auteur(e), mais par toute autre personne qui le reprendrait (voire vous-même, après avoir eu le temps d'oublier le sujet ). Dans cette optique, l'on structurera au maximum les programmes, quitte à "éclater" les procédures en autant de procédures nommées (Subs ou Fonctions). Une autre raison est l'étanchéité entre procédures, que permettent les procédures nommées mais pas Gosub.

Ici, le contexte est différent, et cet exemple se prête bien à l'emploi "parcimonieux" de Goto et Gosub. Moyennant de savoir ce que l'on fait un code à base de ces deux instructions pestiférées peut s'avérer bien plus court que son "équivalent" en programmation structurée. Je ne pars pas en croisade pour la réhabilitation des Goto et Gosub, je rétablis certains faits

e] Donc je "zose"

Reprenons le diagramme de notre jeu. Cherchons-y les étapes sur lesquelles rebouclent plus d'une étape. A première vue, il y en a trois:
* b] Tirage
* c] Saisie d'une Séquence
* j] Fin
Ajoutons-y une quatrième étape, tel que mentionné dans le point correspondant:
* i] MessageBox Question

Insérons donc devant chacune une étiquette, respectivement "L_Tirage:", "L_Saisie:", "L_Bye", et "L_Question:". Notez qu'une étiquette de ligne de type numérique ne requiert pas d'être terminée par le symbole deux-points ":", mais une étiquette alphanumérique oui. Notez aussi que rien ne permet à VB de différencier une étiquette alphanumérique d'une instruction sans paramètres suivie d'un séparateur d'instructions ":" !!! Astuce: précédez alors l'instruction d'un ":" pour éviter la confusion, mais vous perdez l'indentation

Il ne reste plus qu'à mettre en place nos rebouclages par des lignes du type:
IF condition THEN GOTO étiquette
Dans le code que vous trouverez en intégralité à la fin de cet article, j'ai encadré les Etiquettes par des lignes d'apostrophes (commentaires), ce n'est pas une obligation..

5) Des Dollars ?

Parmi les habitudes que j'ai gardées des anciennes versions de Basic, une autre a survécu, l'emploi du symbole Dollar "$" en fin de certaines variables, et même certaines fonctions. De quoi s'agit-il ?

Historiquement, Basic ne savait gérer que deux types intrinsèques de variables, les Numériques (à virgule) et les Chaînes Texte (longueur variable). Afin de différencier les secondes des premières, la convention fut d'affubler les variables Texte du symbole "$". En ce temps, l'instruction DIM n'avait pour seule utilité que de déclarer des Tableaux de Variables.

Le Dollar est donc un Suffixe Déclaratif. VB en gère cinq: "%" pour Integer, "&" pour Long, "!" pour Single, "#" pour Double, et enfin le "$" pour String.

a] Déclarations de Variables

Même si son emploi est fortement déconseillé, Visual Basic a gardé une particularité à double tranchant, la Déclaration implicite des Variables. Qu'est-ce ?

En informatique, tout élément doit être connu avant de pouvoir être utilisé. Et pour cela, il faut le "déclarer". Outre fixer le type de contenu de la Variable, la Déclaration détermine quelle sera sa Portée (ou visibilité, son existence au sein des différents blocs procéduraux du Programme).

La Déclaration Implicite est un souvenir des anciens Basic, associé au type de données appelé Variant. Un Variant est un type de données "polymorphe", capable de "muter" de sous-type en fonction du contenu qu'on lui affecte. Exemple: soit MaVar une variable non déclarée explicitement..
MaVar = "toto" : MaVar = "3" : Mavar = MaVar / 2
Debug.Print MaVar
MaVar est un Variant dont le sous-type sera d'abord String ("toto", puis "3"). "Mavar = MaVar / 2" aurait dû générer une erreur, car on ne peut diviser que des numériques, mais "3" n'est pas 3 !! Peu importe, MaVar étant un Variant, il "mutera" en sous-type Single

Le double tranchant du côté "pratique" de ne pas avoir à se préoccuper des variables, c'est de ne pas avoir forcément la maîtrise des conversions implicites voire de perdre de vue le type de contenu. Si MaVar avait contenu "toto" la division aurait bien généré une erreur.

b] Méthodes de Déclaration

Une Variable non déclarée a pour Portée la Procédure dans laquelle elle apparaît. Son appel dans une autre Procédure créera une Variable homonyme mais distincte.

De même, employer DIM, STATIC, PUBLIC, PRIVATE dans une procédure limite la création à cette Procédure. Particularité de STATIC, la Variable n'est pas détruite mais archivée entre deux appels de la procédure, et sa valeur est conservée.

Employer DIM ou PUBLIC en Zone Déclarations crée des Variables de Portée toute la page (feuille, module..) PUBLIC dans un Module crée des Variables accessibles de tout le Projet.

Une Variable de Portée plus petite peut masquer son homonyme de Portée plus grande.

Si vous décidez d'employer un Suffixe Déclaratif, sachez qu'ils n'existent que pour 5 types précis (voir plus haut), et que même si le Suffixe cohabite avec DIM.. la Variable doit toujours "trimballer" son Suffixe.
Dim X%, Y As Integer
Cette ligne crée deux entiers courts nommés X% et Y, pas X !!

c] Et sur les Fonctions ?

Certaines Fonctions Intrinsèques de VB renvoient des Variants sous-typés. Il est possible de forcer leur sous-type en leur ajoutant un Suffixe Déclaratif. J'aime affubler les Fonctions Texte (ex: MID()) du dollar qui faisait partie de leur nom dans les anciens Basic, peut-être par nostalgie, aussi pour que vous gardiez sous les yeux que ce sont des Fonctions Texte

De même, vous pouvez écrire des Function utilisant As Type ou des Suffixes Déclaratifs..
Function MonTexte$(Txt$)
ou
Function MonTexte(Txt as String) As String

6) Epitaphe logue

Voici donc finie cette (petite) excursion dans le passé assez tumultueux d'un langage pas vraiment aimé à sa juste valeur, le Basic, excursion qui, mine de rien, vous en apprend également un peu plus sur moi

Vous trouverez en sortant (ci dessous), le code complet, à coller n'importe où dans un projet VB..

N'oubliez pas la guide, par le dépôt d'un commentaire

Remarque à l'attention des possesseurs d'Office 2007 et plus: surtout ne sauvegardez PAS votre fichier dans un format "X" (.docX, .xlsX, .pptX, ..) car celui-ci élimine volontairement le code VBA. Préférez les anciens formats, ou les formats "M", autorisant les "Macros" (re-sic).
''''''''''''''
Sub Msg_Mind()
''''''''''''''
Const Nom = "MSG-Mind", Tit = Nom + " (P)08/2010 MyLzz59"
Const CM = 20 ' Nb Coups Maxi
' Question Initiale
If MsgBox("Bienvenue dans " + Nom + vbCrLf + vbCrLf _
+ "Le but consiste à retrouver une séquence" + vbCrLf _
+ "aléatoire de 4 chiffres entre 1 et 8 avec" + vbCrLf _
+ "pour seules indications le nombre de chiffres" + vbCrLf _
+ "bien ou mal placés, en " + CStr(CM) + " coups maximum." + vbCrLf _
+ "Ce jeu fonctionne entièrement en boîtes de dialogue.." + vbCrLf _
+ vbCrLf + " [Oui]:Jouer, [Non]:Quitter" _
, vbExclamation + vbYesNo, Tit) <> vbYes Then GoTo L_Bye
'''''''''
L_Tirage:
'''''''''
' Nouveau Tirage
M$ = "": C = 1: Z0$ = "": Randomize Timer
For T = 1 To 4: Z0$ = Z0$ + CStr(1 + Int(Rnd * 8)): Next T
'''''''''
L_Saisie:
'''''''''
' Saisie d'une Séquence
Z$ = InputBox("Coups joués précédemment :" + vbCrLf + vbCrLf _
+ M$ + vbCrLf + "Coup n° " + CStr(C) + " :", Tit)
' Saisie Vide (Annuler)
If Z$ = "" Then B = True: Q$ = "Vous avez annulé la Saisie..": GoTo L_Question
' Validité de la Saisie ?
B = True: Z$ = Left$(Trim$(Z$) + " ", 4)
For T = 1 To 4: B = IIf(InStr("12345678", Mid$(Z$, T, 1)), B, False): Next T
If B = False Then
MsgBox """" + Z$ + """ n'est pas valide.", vbExclamation, Tit: GoTo L_Saisie
End If
' Coup Déjà Joué
If InStr(M$, ": " + Z$ + " =") Then
MsgBox """" + Z$ + """ a déjà été joué.", vbExclamation, Tit: GoTo L_Saisie
End If
' Test Gagné
Z1$ = Z$: Z2$ = Z0$: BP = 0: MP = 0
For T = 1 To 4
If Mid$(Z1$, T, 1) = Mid$(Z2$, T, 1) Then
Mid$(Z1$, T, 1) = "*": Mid$(Z2$, T, 1) = "@": BP = BP + 1
End If
Next T
For T = 1 To 4
For T2 = 1 To 4
If Mid$(Z1$, T, 1) = Mid$(Z2$, T2, 1) Then
Mid$(Z1$, T, 1) = "*": Mid$(Z2$, T2, 1) = "@": MP = MP + 1
End If
Next T2
Next T
M$ = M$ + "Coup n° " + Format$(C, "00") + " : " + Z$ + " => " _
+ CStr(BP) + " bien et " + CStr(MP) + " mal placé(s)" + vbCrLf
If BP = 4 Then B = False: Q$ = M$ + vbCrLf + "!! Bravo c'est Gagné !!": GoTo L_Question
' Test Perdu
C = C + 1
If C > CM Then B = False: Q$ = M$ + vbCrLf + "Perdu, il fallait trouver """ _
+ Z0$ + """": GoTo L_Question
GoTo L_Saisie
'''''''''''
L_Question:
'''''''''''
' Question dans le Jeu
Select Case MsgBox(Q$ + vbCrLf + vbCrLf _
+ "[Oui]: Recommencer une Nouvelle Partie" + vbCrLf _
+ "[Non]: Quitter " + Nom + vbCrLf _
+ IIf(B, "[Annuler]: Revenir à la Saisie" + vbCrLf, "") _
, IIf(B, vbYesNoCancel, vbYesNo) + vbDefaultButton3 + vbInformation, Tit)
Case vbYes ' Rejouer
GoTo L_Tirage
Case vbNo ' Quitter
Case Else ' Annuler
GoTo L_Saisie
End Select
''''''
L_Bye:
''''''
' Sortie
MsgBox "Bye..", vbInformation, Tit
End Sub

-MyLzz59-

[25/10/2010] Correction d'un bug dans le contrôle de validité: la comparaison considérait, si moins de quatre caractères étaient saisis, ceux manquants comme valides. Aussi, complète-t-on des espaces, invalides..

2 Commentaire(s):

Stéphane a dit…
Youpiiii! Une encyclopédiiiie!

Quelle somme de boulot! C'est incroyable... :-)
Je n ai pas essayé le code (ni essayé de le comprendre :p ) (aiiieeeuuuu...) (mais si j essaierai! faudra juste que j'allume un pc!) ( faudrait aussi que je l imprime)
J ai par contre dévoré la petite histoire du Basic... (là, j ai compris; enfin faudrait pas qu'il y ait interro demain matin non plus! ;-) )

bisous Miss...
je reviendrai dessus quand j aurai tésté..
ps: on avait remarqué avec mon gamin que classiquement, on gagnait en 6 coups ;-) (ou 5, j'me souviens pû)
Mylène (MyLzz59) a dit…
Woaw ! T'avais du temps à perdre, Taz ? ;)

Je me doute bien que tu finiras par tester le code, c'est ton côté "démonte-tout", je connais aussi :P

Ravie de t'avoir amusé avec mes "souvenirs de guerre" :) Plus on vieillit, dit-on, plus on radote sur le temps d'avant, qu'est mort et dont tous les autres se foutent, et qu'on n'ose pas dire qu'on regrette, car ça va à l'inverse de l'idée de progrès qu'on nous force à gober continuellement..

Sinon, ce code, je te le re^n-dis, il est vraiment très simple ! Quelques boîtes messages, quelques boîtes de saisie, et quelques GOTO (wouah-ah-ah-ah-ah !!!! :D)

Bisous mon si courageux lecteur :*
-MyLzz59-