Il est de bon ton de se souhaiter la bonne année. Mais vous, et vous seul, pourrez faire en sorte que cette année soit bonne, meilleure que celle qui vient de s'écouler. Apprenez à ne compter que sur vous, car personne n'est plus qualifié que vous-même pour bâtir, réparer ou améliorer votre propre vie. Personne ne fera les choses à votre place. D'ailleurs, tout ce que les autres peuvent faire, c'est souhaiter que vous le fassiez. Et ne croyez pas que tout ceux qui vous entourent vous apporteront des solutions : certains font juste partie de vos problèmes. Transformez vos résolutions en actes, et dans douze mois, retournez-vous et souriez-vous fièrement : C'était long. C'était difficile. Mais ça y est : 2017 était une bonne année, merci Moi.

Access

Qui veut gagner des millions ?

Dans ce didacticiel, nous allons programmer une version allégée du jeu "Qui veut gagner des millions", la célèbre émission de télévision, animée par Jean-Pierre Foucault.

Je vous propose de télécharger ce fichier.zip sur votre PC et de décompresser tous les fichiers qui s'y trouvent dans le dossier de votre choix de votre ordinateur.

 

 
Sommaire
  1. Mode d'emploi
  2.   Ecran d'accueil
  3.   Utilisation des Jokers
  4.   Choix de la réponse
  5.   Choix d'une mauvaise réponse
  6.   Difficulté des questions
  7.   Retour aux mêmes questions
  8.   Création, modification, suppression des questions
  9. Fonctionnement technique
  10.   Fichiers externes nécessaires
  11.   Objets de la base de données
  12.   Jouer de la musique dans Access
  13.   Invocation d'un fichier DLL
  14.   Chemin d'accès de la base de données
  15.   Utilisation de la minuterie
  16.   Minuterie ne s'exécute qu'une seule fois
  17.   Variables globales
  18.   Tout le code VBA de F_Jeu
  19.   Evénement Form_Open (Ouverture du formulaire)
  20.   Evénement Form_Current (Arrivée sur un enrefgistrement)
  21.   Gestion des couleurs RGB (Red Green Blue)
  22.   Paramètres non-programmés
  23.   Musique de fond des questions
  24.   DoEvents
  25.   Gestion du clic sur les réponses
  26.   Procédure générale du traitement des réponses
  27.   Préparation du texte en cas de bonne réponse
  28.   Le joueur a-t-il cliqué sur la bonne réponse ?
  29.   Le joueur a choisi la bonne réponse
  30.   Effets de boutons en relief
  31.   Procédure en cas de gain d'un million d'euros
  32.   Le joueur a choisi une mauvaise réponse
  33.   Clic sur le bouton vert "Prochaine question"
  34.   Actualisation de l'échelle des gains
  35.   Affichage d'une image dynamiquement
  36.   Gestion des erreurs (On Error GoTo)
  37.   Clics sur les jokers
  38.   Fonctionnement du joker 50/50
  39.   Génération contrôlée de nombres aléatoires avec Rnd()
  40.   Fonction Int() (Nombre entier)
  41.   Boucle While -Wend
  42.   Code complet du joker 50/50
  43.   Idées d'améliorations possibles du programme

Mode d'emploi

Jouer avec un beamer

L'idée est de jouer entre amis, sur un écran géant, ou avec un beamer.

A la base, j'ai créé ce programme pour animer l'anniversaire d'une amie. J'avais branché mon ordinateur sur un beamer (projecteur), et chaque personne répondait à une question concernant directement l'amie dont c'était l'anniversaire. les questions n'étaient donc pas de culture générale, mais uniquement des questions sur cette amie (Quelle est ma pointure de chaussure ? ... Quel est mon signe du zodiaque, etc.)

Les questions sont très faciles à changer puisqu'elles se trouvent toutes dans l'unique table T_Questionnaire.

Lorsque la personne dont c'était le tour choisssait le joker "Coup de fil à un ami" , en fait, il demandait de l'aide à une personne de l'assistance. Et lorsqu'il demandait L'avis du public , c'est l'animateur (moi), qui demandait à la cantonnade : "Ceux qui pensent que c'est la réponse A lèvent la main"... "Ceux qui pensent que c'est la réponse B lèvent la main", et ainsi de suite avec C et D. Le candidat s'inspirait donc du nombre des bras levés.

Ecran d'accueil

Lorsque vous aurez décompressé le contenu de votre millions.Zip dans un dossier de votre PC, il vous suffira de double-cliquer sur Qui veut gagner des millions.accdb. Access se lancera, et ouvrira cette base de données.

Dès que le programme sera ouvert, vous entendrez la musique de générique et vous serez devant le formulaire F_Generique :

 

Attendez que la musique soit terminée, et l'autre formulaire F_Jeu va automatiquement s'afficher :

Vous êtes dans la première question. Vous jouez pour 200€, comme c'est indiqué sur l'échelle des gains à droite.

Utilisation des jokers

Vous avez droit aux trois jokers traditionnels de l'émission :

le 50/50 : l'ordinateur va retirer deux mauvaises réponses, comme dans la vraie émission.

Le coup de fil à un ami. Lorsque vous cliquez sur ce bouton, vous entendrez la musique traditionnelle de l'appel à un ami, mais ici, l'ami en question sera quelqu'un que vous appellerez dans l'assistance.

L'avis du public : lorsque vous cliquez sur ce bouton, vous entendrez aussi la musique traditionnelle du vote du public, mais, comme je l'ai précisé plus haut, c'est l'animateur qui demande à la cantonnade quelle réponse ils supposent.

Chaque fois qu'un joker est utilisé, il disparaît simplement de la liste.

Choix de la réponse

Lorsque vous cliquez sur la réponse A, B, C ou D, vous entendez soit le son de la victoire, soit un vilain Buzz.

Lorsque vous cliquez sur la bonne réponse, les trois autres réponses s'affichent en rouge, et un bouton vert apparaît, qui vous rappelle la somme gagnée.

Dès que vous cliquez sur ce bouton vert, la question suivante apparaît, le bouton vert disparaît, et l'échelle des gains augmente.

En bas de votre écran, vous pouvez voir à quelle question vous êtes (Ici, la 2ème) sur un total de combien (28 dans notre cas). ce sont simplement les questions que vous retrouverez dans la table T_Questionnaire que vous pourrez par la suite modifier comme bon vous semble.

Si vous cliquez sur les jokers, ils disparaissent.

Attention : vous devez chaque fois attendre que la musique s'arrête avant de cliquer sur le joker suivant ou sur une réponse : c'est une des limitations de ce jeu avec Access, je ne suis pas arrivé à trouver une astuce qui me permet de continuer à jouer alors qu'une musique est en train de se jouer.

Si vous cliquez sur une mauvaise réponse, un texte en rouge vous le signale :

Choix d'une mauvaise réponse

Quand vous répondez mal, et que vous cliquez sur le bouton rouge "Perdu", c'est comme si on passait à un autre candidat :

 

 

 

Dans le vrai jeu, une fois que le candidat a la question en face de lui, il peut simplement s'abstenir de répondre et ainsi empocher ses gains. J'aurais pu ajouter un bouton "J'empoche mes gains", mais je ne voyais pas trop l'intérêt... Dans le cas ou vous jouez sur un écran géant, et que vous assurez l'animation, il suffit que le candidat vous dise "J'arrête" pour simplement lui répondre "vous avez gagné tant d'euros", en se référant à l'échelle des gains sur la droite.

Difficulté des questions

Les questions ne sont pas de difficulté croissante, elles aussi faciles/difficiles que vous le désirez, puisque c'est vous qui les créerez dans la table T_Questionnaire. Pour que ce jeu soit plus conforme à la réalité, j'aurais pu l'affiner, et proposer des questions très faciles pour les 4 premières questions, puis de difficulté moyenne pour le premier palier (questions 6 à 10) et difficiles pour les questions 11 à 15, mais ç'aurait été trop complexe à mon goût pour un programme que je voulais relativement facile à comprendre et à analyser.

Retour aux mêmes questions

Si vous jouez suffisamment longtemps pour arriver à la dernière question
(), le signal sonore typique signalant la fin d'émission retentit, et une boîte de dialogue vous informant que vous avez fait le tour des questions s'affiche :

Le programme ne s'arrête toutefois pas, et vous pouvez continuer à jouer en recomnmençant les mêmes questions depuis le début, comme s'il s'agissait de nouvelles questions (Personnellement, je trouve peut-être un peu idiot de reposer les mêmes questions, mais bon, je trouvais sympa de permettre de continuer à jouer comme si de rien n'était).

Création, modification et suppression de ses propres questions

Pour modifier les questions et les réponses, fermez votre formulaire, et ouvrez simplement la table T_Questionnaire.

Le fonctionnement est vraiment simple : vous écrivez votre question, puis vous décidez quelle sera la bonne réponse dans le champ BonneReponse, puis vous écrivez la bonne réponse dans R1, R2, R3 ou R4 selon ce que vous avez décidé, et vous mettez des réponses fantaisistes dans les autres champs, comme dans cet exemple :

Vous pouvez remplacer les questions existantes par les vôtres, ou carrément effacer le questionnaire pour en recréer un nouveau à votre goût. Pour ce faire, appuyez sur CTRL-A (Pour tout sélectionner), et appuyez sur la touche DEL ou SUPPR de votre clavier. Répondez Oui à la question.

Vous pourrez maintenant réécrire des questions et réponses de votre cru.

Fonctionnement technique

des fichiers externes nécessaires

Objets de la base de données

Concernant la base de données, elle-même, Je n'ai pas eu besoin de beaucoup d'objets pour créer ce jeu :

Aucune requête ni état n'a été nécessaire.

 

Pour que F_Generique s'affiche automatiquement lors de l'ouverture de la base de données, il suffit de se rendre dans le menu Fichier/Options Access :

J'en profite pour attribuer un titre convivial qui s'affichera au milieu de la barre de titre :

Si vous voulez ouvrir cette base de données sans pour autant ouvrir automatiquement F_Generique, il vous suffit d'appuyer et de laisser le doigt sur la touche MAJUSCULE de votre clavier le temps d'ouvrir de la base.

Ce formulaire F_Generique est simpliste : Il ne se base sur aucune table, et ne contient rien d'autre que l'image-logo de "voulez-vous gagner des millions".

En même temps qu'il s'affiche, la musique du générique se joue !

Jouer de la musique dans Access

Nous allons devoir utiliser un fichier DLL (Dynamic Link Library). Plein de choses peuvent être directement réalisées par VBA, mais pas tout : par exemple, jouer de la musique n'est pas dans ses attributions. Aussi, nous allons lui demander de solliciter Môssieur Windows afin qu'il nous rende quelques menus services. Nous avons besoin d'un fichier nommé Winmm.dll, qui se trouve bien planqué au fond de votre ordinateur. Ce fichier Winmm.dll contient des petites fonctions bien utiles, comme par exemple, la possibilité de jouer de la musique.

J'ai dû créer un module VBA à part, comme ceci :

 

 

Dans ce module VBA, j'ai invoqué le fichier DLL, tout bien comme il faut :

Vous voyez ce module ici :

Invocation du fichier DLL

Il y a deux parties dans ce code VBA :

Première partie : La préparation à l'appel de la fonction sndPlaySound
Public Declare Function sndPlaySound32 _ Lib "winmm.dll" _ Alias "sndPlaySoundA" ( _ ByVal lpszSoundName As String, _ ByVal uFlags As Long) As Long
Deuxième partie : La création d'une procédure qui permet d'appeler sndPlaySound de manière conviviale
Sub Joue(FichierMusique) FichierMusique = Application.CurrentProject.Path & "\" & FichierMusique sndPlaySound32 FichierMusique, 0& End Sub
Malheureusement, on ne peut jouer que des .wav qui sont nettement plus volumineux que des .MP3 avec cette technique. Je n'ai pas trouvé de manière de jouer des .MP3 au sein-même d'Access.
Ce n'est pas moi qui ai inventé ce code, mais je l'ai trouvé en cherchant sur Google "jouer de la musique avec vba", et j'ai simplement copié-collé-adapté la solution que j'ai trouvé.

Pour tester cette procédure, et voir si ça marche, il suffit de créer une petite procédure en dessous, comme ceci :

Ensuite, il suffit de cliquer quelque part dans votre procédure, et d'appuyer sur la touche F5 :

Normalement, vous devriez entendre un son sec (le son qu'on entend quand on clique sur le joker "50/50").

Chemin d'accès de la base de données

Il sait a quel endroit se trouve le fichier musical : au même emplacement que la base de données elle-même, puisque je précise Application.CurrentProject.Path (Chemin d'accès de la base de données, donc pas d'erreur possible), suivi de \ :

VBA
Sub Joue(FichierMusique) FichierMusique = Application.CurrentProject.Path & "\" & FichierMusique sndPlaySound32 FichierMusique, 0& End Sub
La section que nous venons d'étudier (Public Declare Function sndPlaySound32, etc.) doit impérativement se trouver dans un module à part. Si je l'avais écrit dans le module du formulaire (Au dessus de Private Sub Open (Cancel As Integer) par exemple), ça n'aurait pas fonctionné.

 

 

Ainsi, dès l'ouverture du formulaire F_Generique, il faut jouer GagneMillionFinal.wav (Qui est donc aussi la musique du générique).

Utilisation de la minuterie

Dans le formulaire F_Generique, en mode création, vous remarquerez que je ne me suis pas simplement contenté de mettre Joue "GagneMillionFinal.wav" dans l'événement Sur Ouverture, mais j'ai dû ruser avec la minuterie !

Si je m'étais contenté de ce code :

VBA
Private Sub Form_Open(Cancel As Integer) Joue "GagneMillionFinal.wav" End Sub

Il aurait effectivement joué la musique, mais le formulaire F_Generique se serait affichée après que la musique soit finie ! Pourquoi ? je n'en sais rien ! Môssieur Access a décidé qu'il fallait jouer la musique, puis seulement après, afficher le formulaire avec le logo !

Comment contourner un tel bug ???

Puisqu'il faut lui laisser le temps d'afficher le formulaire, puis seulement après jouer la musique, je vais utiliser l'événement Sur Minuterie. Sur Minuterie permet de réaliser des actions VBA tous les X temps. Tous les Intervalle Minuterie Millisecondes. Par exemple, si Sur Minuterie, vous placez le code VBA Joue "50-50.wav", et que dans Intervalle minuterie, vous écrivez 7000, alors, quand vous lancerez votre formulaire en mode saisie de données, au bout de 7000 millisecondes
(7 secondes donc), il va jouer le son sec du 50-50, et il va recommencer automatiquement
7 secondes plus tard, et ainsi de suite, sans jamais se lasser.

Moi, je ne veux pas attendre 7 secondes avant qu'il commence à jouer GagneMillionFinal.wav, c'est trop long, et en plus, je ne veux pas qu'il le répète plusieurs fois !

Du coup, au lieu de 7000, j'ai mis 1 dans intervalle minuterie , comme ça il patiente un millième de seconde. C'est très court, un millième de seconde, mais ça suffit à Access pour afficher le formulaire avant tout, puisque c'est ça qu'on veut.

Minuterie qui ne s'exécuute qu'une seule fois

Il va donc répéter le code VBA Sur Minuterie tous les un millième de seconde : comment faire pour qu'il ne l'exécute qu'une seule fois ?

VBA
Private Sub Form_Timer() If VARMinuterieGenerique = True Then Exit Sub Joue "GagneMillionFinal.wav" VARMinuterieGenerique = True DoCmd.OpenForm "F_Jeu" End Sub

VARMinuterieGenerique est une variable booléenne (c'est à dire que tout ce qu'on peut lui attribuer comnme valeur, c'est True (Vrai) ou False (Faux). C'est moi qui l'ai inventée (J'aurais pu l'appeler TarteAuCitron au lieu de VARMinuterieGenerique que ça aurait tout aussi bien fonctionné).

Comme elle est toute neuve, elle vaut False

La première fois que ce code est exécuté, il commence par vérifier si VARMinuterieGenerique = True. Est-ce que cette variable vaut true ? Non, on ne sait même pas ce qu'elle vaut puisqu'on vient de commencer à l'utiliser !

Si VARMinuterieGenerique = True, il faut Exit Sub : c'est à dire immédiatement sortir de la procédure sans plus rien faire : aller directement au End Sub sans détour !

Est-ce que VARMinuterieGenerique = True ? Non, on vient de le voir.

Du coup, hop : Musique ! Joue "GagneMillionFinal.wav" !

Immédiatement après, on ouvre F_Jeu (DoCmd.OpenForm "F_Jeu"). Mais comme on lui demande d'ouvrir immédiatement F_Jeu sans délai, on aura juste un millième de seconde pour apprécier le logo de F_Generique, et boum, il affiche F_Jeu en terminant de jouer GagneMillionFinal.wav, non ? ... Eh bien non ! Lorsque Access joue GagneMillionFinal.wav, il attend bien sagement que la musique soit finie pour sauter à l'instruction suivante DoCmd.OpenForm "F_Jeu".

Ca tombe bien : c'est exactement ce que je veux !

Revenons à notre minuterie. Une fois que tout est fini, il va rejouer la musique un millième de seconde plus tard ! Il va à nouveau tomber sur If VARMinuterieGenerique = True Then Exit Sub ! Et cette fois-ci, effectivement, VARMinuterieGenerique = True, puisque c'est ce qu'on lui a précisé au tour d'avant qu'on était dans ce code, il y a un millième de seconde. Dorénavant, peu importe le nombre de fois que cette procédure est exécutée, VARMinuterieGenerique = True et donc, hop : direct au End Sub !

Ca, ce serait idéal ! Dans la pratique, ça ne marche pas comme ça ! Dès qu'il arrive sur End Sub, et sort de la procédure et il perd la mémoire ! On a eu beau avoir dit très clairement que VARMinuterieGenerique = True, dès qu'il arrive sur End Sub, VBA est atteint d'un Alzheimer foudroyant, et VARMinuterieGenerique est à nouveau dans son état initial : False !

Tous les millièmes de seconde, la musique va se rejouer, encore et encore !

Variables globales

Heureusement, nous disposons d'un manière de doter les variables d'une mémoire indestructible. Cette variable VARMinuterieGenerique va continuer à être mémorisée avec la valeur que nous lui attribuons, même après la fin du End Sub.

Pour ce faire, nous allons la déclarer comme ceci dans un module à part. Et puisque nous en disposons déjà d'un (celui qui contient les instructions pouir la musique), nous allons le compléter :

VBA
Option Compare Database Option Explicit Global VAREchelle Global VARMinuterieGenerique As Boolean Global VARMusiquePremiereQuestion As Boolean Public Declare Function sndPlaySound32 _ Lib "winmm.dll" _ Alias "sndPlaySoundA" ( _ ByVal lpszSoundName As String, _ ByVal uFlags As Long) As Long ...

Grâce à cette déclaration, nous avons le beurre et l'argent du beurre : la musique se joue, une seule fois, une milliseconde après que le formulaire se soit chargé (Autant dire tout de suite).

Une fois que la musique de générique se termine, j'ouvre donc F_Jeu (DoCmd.OpenForm "F_Jeu"), qui est basé sur la table T_Questionnaire :

Tout le code VBA de F_Jeu

Si vous vous rendez dans VBA, vous verrez les kilomètres de code que j'ai pondu.

Sur Ouverture de F_Jeu, il se passe déjà des choses au niveau de VBA, notamment la fermeture de F_Generique :

VBA
Private Sub Form_Open(Cancel As Integer) ' Pas de musique pour la première question, car ça retarde l'affichage du formulaire : VARMusiquePremiereQuestion = False ' On ferme F_Generique, car ça ne sert à rien de laisser ce formulaire ouvert, surtout avec la minuterie ' qui se déclenche toutes les millisecondes (même s'il ne se passe rien) DoCmd.Close acForm, "F_Generique" VAREchelle = 1 End Sub

J'ai également créé une variable globale comme tout à l'heure, qui s'appelle VARMusiquePremiereQuestion, que j'initialise à False lors de l'ouverture du formulaire (Cette initilaisation est facultative puisque par défaut, une variable Booléenne est définie à False dès sa création). Vous pouvez voir sa déclaration dans le module P_Divers.

J'ai créé cette variable uniquement pour éviter la musique lors de la première question, car ça retarde l'affichage du formulaire, et je n'avais pas envie d'utiliser la minuterie comme dans F_Generique. Comme on vient d'entendre la musique de générique, je trouvais plus sympa de proposer cette première question en silence.

VAREchelle = 1 signifie que nous sommes au premier échelon de l'échelle des gains (forcément, puisqu'on vient d'ouvrir le formulaire).

Dès que vous arrivez sur un nouvel enregistrement, Sur Activation se déclenche. La première fois que Sur Activation se déclenche, c'est automatiquement juste après Sur Ouverture, puisqu'on "Active" le premier enregistrerment.

Evénement Form_Open (Ouverture du formulaire)

Private Sub Form_Open(Cancel As Integer) est ce qui s'exécute une seule fois dès l'ouverture du formulaire. Du code VBA est aussi exécuté à chaque activation d'un enregistrement.

Evénement Form_Current (Arrivée sur un enregistrement)

Voici ce qui se passe déjà maintenant pour la première fois, juste après Form_Open:

VBA
Private Sub Form_Current() ' Remise de toutes les réponses visibles, des fois qu'on ait cliqué ' sur 50/50 à la question d'avant TXTR1.Visible = True TXTR2.Visible = True TXTR3.Visible = True TXTR4.Visible = True ' Remise en couleur blanc de toutes les réponses :
ForeColor représente la couleur des caractères, alors que BackColor représenterait la couleur de fond de la zone de texte.
TXTR1.ForeColor = RGB(255, 255, 255) TXTR2.ForeColor = RGB(255, 255, 255) TXTR3.ForeColor = RGB(255, 255, 255) TXTR4.ForeColor = RGB(255, 255, 255) ' Initialisation de la questions : TXTQuestion.Caption = Question ' Affichage des 4 réponses possibles : TXTR1.Caption = R1 TXTR2.Caption = R2 TXTR3.Caption = R3 TXTR4.Caption = R4 DoEvents ' Musique ! ' Ne pas jouer la musique lors de la première question, car le formulaire ne s'affiche qu'après : If VARMusiquePremiereQuestion = True Then Joue "MusiqueFondQuestion.wav" End If VARMusiquePremiereQuestion = True End Sub

Dans cette "Activation", il est beaucoup question de TXTR1, TXTR2, TXTR3, et TXTR4. ce sont les quatre réponses possibles : des zones de TeXTe que j'ai créé, dont j'ai changé le fond en "Transparent", écriture blanche, et police de caractères Arial, taille 16, gras.

Vous avez donc compris que TXT1, ce sera la réponse A, TXT2, la B, TXT3 = C et TXT4 = D.

Dans la procédure Sur Activation, je commence par les rendre toutes visibles :

VBA
TXTR1.Visible = True TXTR2.Visible = True TXTR3.Visible = True TXTR4.Visible = True

Sans intérêt pour l'instant, on en verra l'utilité lorsque nous utiliserons le joker 50/50 qui, justement, efface (Visible = False) deux mauvaises réponses.

Gestion des couleurs RGB (Red Green Blue)

La propriété ForeColor représente la couleur des caractères : on affiche toutes les réponses en blanc. Ca n'a aucun intérêt non plus lors de la première question, puisque les réponses sont déjà en blanc. C'est au moment où nous cliquerons sur une réponse que les trois mauvaises réponses deviendront rouges. dès qu'on arrive à la question suivante, les réponses devront à nouveau être blanches.)

VBA
TXTR1.ForeColor = RGB(255, 255, 255) TXTR2.ForeColor = RGB(255, 255, 255) TXTR3.ForeColor = RGB(255, 255, 255) TXTR4.ForeColor = RGB(255, 255, 255)

 

J'ai utilisé la fonction RGB (Red , Green, Blue), alors que la couleur des caractères est indiquée dans les propriétés sous forme hexadécimale. Je ne voudrais pas ici m'éterniser dans de longues considérations colorées sur la représentation informatique des couleurs, mais je vous informe juste que les couleurs possibles sont numérotées de 1 à FFFFFF (qui est égal à 16'777'215). On peut représenter une couleur par un simple chiffre, ou alors par la quantité de rouge, de vert et de bleu, qui s'échelonnent chacune de 0 à 255. (de 0 à FF car FF veut dire 255 en hexadécimal).

Je ne vais donc pas m'embarquer dans un cours sur ce sujet, mais voyez comment vous pouvez visualiser les deux manières sur ce schéma :

Paramètres non-programmés

Vous pourriez me demander pourquoi je ne précise pas en VBA que la zone de texte est transparente, en gras et Arial taille 16, car ce serait techniquement possible . Ca ne sert à rien : ces propriétés ont été définies "en dur" lors de la conception du formulaire, et rien, aucune action, aucun événement ne modifiera ces propriétés, tandis que la couleur du texte, elle, va changer dynamiquement (passer au rouge pour mettre en évidence les réponses fausses)

 

Je transfère ensuite le contenu des champs du premier enregistrement de ma table T_Questionnaire dans les différentes zones (Rien de difficile, puisque le formulaire F_jeu est basé sur T_Questionnaire)  :

Musique de fond des questions

Et enfin, nous allons gérer la musique. Lors de la première question, la musique ne se joue pas. Dès la 2ème question et les suivantes, If VARMusiquePremiereQuestion = True Then, sera toujours Vrai, et la musique se fera entendre.

VBA
DoEvents ' Musique ! ' Ne pas jouer la musique lors de la première question, car le formulaire ne s'affiche qu'après : If VARMusiquePremiereQuestion = True Then Joue "MusiqueFondQuestion.wav" End If VARMusiquePremiereQuestion = True

DoEvents

A quoi sert le DoEvents avant le If ?

Il est indispensable : Observez la procédure de haut en bas :

VBA
Private Sub Form_Current() TXTR1.Visible = True TXTR2.Visible = True TXTR3.Visible = True TXTR4.Visible = True TXTR1.ForeColor = RGB(255, 255, 255) TXTR2.ForeColor = RGB(255, 255, 255) TXTR3.ForeColor = RGB(255, 255, 255) TXTR4.ForeColor = RGB(255, 255, 255) TXTQuestion.Caption = Question TXTR1.Caption = R1 TXTR2.Caption = R2 TXTR3.Caption = R3 TXTR4.Caption = R4 DoEvents If VARMusiquePremiereQuestion = True Then Joue "MusiqueFondQuestion.wav" End If VARMusiquePremiereQuestion = True End Sub

On voit bien qu'il commence par afficher les réponses (Visible = True), il les remet en blanc, puis il affiche la question actuelle et les réponses possibles (TXTQuestion.Caption = Question, TXTR1.Caption = R1, ...), puis seulement, il joue la musique en fond sonore de la question.

On s'attend logiquement à ce que la nouvelle question et les réponses possibles soient affichées avant que la musique se mette à jouer.

Eh bien non !

Access parcourt tout le code VBA, joue la musique, et seulement après, remet les réponses en blanc et affiche la question et les réponses suivantes !

Ce n'est pas très logique !

Le code VBA devrait s'exécuter de haut en bas : pas faire d'abord ce qui y a en bas, puis le reste quand la musique est finie !

Si on n'installe pas le DoEvents, vous entendrez la musique de la question se jouer,  et seulement à la fin de la musique, la nouvelle question et les nouvelles réponses (et vous verrez l'ancienne question et les anciennes réponses durant tout le temps de la musique).

DoEvents est une manière de dire à VBA : "Tu finis d'abord tout ce qui est au dessus, et seulement quand tu as fini ton assiette, tu vas manger ton dessert, c'est à dire tu joues la musique".

Je ne sais pas pourquoi il fait parfois les choses dans le désordre.

Gestion du clic sur les réponses

Lorsque vous cliquez sur une réponse A, B, C ou D, VBA vous renvoie d'abord à la procédure générale TraitementReponse :

VBA
' Choix du candidat : REPONSE A Private Sub TXTR1_Click() TraitementReponse DoEvents If BonneReponse = 1 Then BDCQuestionSuivante.Visible = True DoEvents Joue "reponseexacte.wav" GagneMillion Else Joue "MauvaiseReponse.wav" Perdu End If End Sub ' Choix du candidat : REPONSE B Private Sub TXTR2_Click() TraitementReponse DoEvents ... End Sub ' Choix du candidat : REPONSE C Private Sub TXTR3_Click() TraitementReponse DoEvents ... End Sub ' Choix du candidat : REPONSE D Private Sub TXTR4_Click() TraitementReponse DoEvents ... End Sub

TraitementReponse est la procédure qui contient tout ce qu'il faut effectuer de toute façon (que la réponse soit correcte ou pas).

Pour vous rendre directement sur TraitementReponse, sans avoir besoin de le chercher dans le code VBA, vous pouvez cliquer sur un des TraitementReponse que vous voyez, et appuyer sur MAJ F2.

Procédure générale du traitement  des réponses

Analysons TraitementReponse, étape par étape :

VBA
Sub TraitementReponse() ' Coloration de toutes les réponses en rouge ... : TXTR1.ForeColor = RGB(255, 0, 0) TXTR2.ForeColor = RGB(255, 0, 0) TXTR3.ForeColor = RGB(255, 0, 0) TXTR4.ForeColor = RGB(255, 0, 0) ' ... Et coloration de la bonne réponse en vert : Select Case BonneReponse ... End Sub

Pour commencer, je colore toutes les réponses en rouge. Même si la réponse est correcte, hop, rouge !

Ca me simplifie la vie car à l'étape suivante, il me suffit de colorer en vert l'unique bonne réponse, en me basant sur le champ BonneReponse de la table T_Questionnaire. Il est vrai que ce champ BonneReponse n'apparaît pas dans le formulaire, même en champ masqué, mais il est quand même bien présent, et je peux y faire référence sans problème en VBA. Selon la valeur (Select Case) du champ BonneReponse (Qui ne peut contenir par définition, que 1,2,3 ou 4)

VBA
Sub TraitementReponse() ... TXTR4.ForeColor = RGB(255, 0, 0) ' ... Et coloration de la bonne réponse en vert : Select Case BonneReponse Case 1: TXTR1.ForeColor = RGB(0, 255, 0) Case 2: TXTR2.ForeColor = RGB(0, 255, 0) Case 3: TXTR3.ForeColor = RGB(0, 255, 0) Case 4: TXTR4.ForeColor = RGB(0, 255, 0) End Select ' Personnalisation du bouton "Question suivante" Select Case VAREchelle ...

Préparation du texte en cas de bonne réponse

L'étape suivante de TraitementReponse peut paraître illogique.

VBA
Sub TraitementReponse() ... Case 4: TXTR4.ForeColor = RGB(0, 255, 0) End Select ' Personnalisation du bouton "Question suivante" Select Case VAREchelle Case 1: texte = "Vous avez 200€." Case 2: texte = "Vous avez 300€." Case 3: texte = "Vous avez 500€." Case 4: texte = "Vous avez 800€." Case 5: texte = "Vous avez 1500€. C'est le premier palier" Case 6: texte = "Vous avez 3000€." Case 7: texte = "Vous avez 6000€." Case 8: texte = "Vous avez 12'000€." Case 9: texte = "Vous avez 24'000€." Case 10: texte = "Vous avez 48'000€. C'est le deuxième palier" Case 11: texte = "Vous avez 72'000€." Case 12: texte = "Vous avez 100'000€." Case 13: texte = "Vous avez 150'000€." Case 14: texte = "Vous avez 300'000€." Case 15: texte = "Vous avez 1'000'000€. BRAAAVOOOO !!!" End Select texte = texte & Chr(13) & Chr(10) & "Cliquez ici pour la prochaine question." BDCQuestionSuivante.Caption = texte End Sub

Il s'agit de préparer le terrain du bouton qui va bientôt s'afficher.

Selon la valeur de la variable VAREchelle, la variable locale texte va contenir un texte différent. VAREchelle est une variable globale que nous avons déclarée dans le module à part P_Divers, car il ne faut pas que son contenu s'oublie dès la fin de la procédure. Elle a été initialisée à 1 lors de l'ouverture du formulaire (Vous pouvez vérifier ça dans Form_Open). Elle vaut donc, ici, toujours 1.

texte est une variable locale que j'ai inventée, mais que je n'ai déclarée nulle part (oui, on peut utiliser des variables comme ça, à la volée) Peu m'importe que son contenu soit perdu à la fin de la procédure, j'en ai juste besoin pour stocker un petit texte (Vous avez 200€).

A la fin du texte "Vous avez 200€", je rajoute le texte "Cliquez ici pour la prochaine question":

texte = texte & Chr(13) & Chr(10) & "Cliquez ici pour la prochaine question."

Le Chr(13) & Chr(10)  permet de passer à la ligne (comme la touche ENTER)

Je disais que cette procédure peut paraître illogique parce que tout laisse à penser qu'on a cliqué sur la bonne réponse, alors que rien n'est moins sûr. En fait, le bouton vert est prêt à être affiché en cas de bonne réponse, mais il est toujours invisible pour l'instant.

Le joueur a-t-il cliqué sur la bonne réponse ?

Nous arrivons sur End Sub, et nous revenons donc là où nous étions (juste après la ligne d'appel à TraitementReponse)

VBA
' Choix du candidat : REPONSE A Private Sub TXTR1_Click() TraitementReponse DoEvents If BonneReponse = 1 Then BDCQuestionSuivante.Visible = True DoEvents Joue "reponseexacte.wav" GagneMillion Else Joue "MauvaiseReponse.wav" Perdu End If End Sub ' Choix du candidat : REPONSE B Private Sub TXTR2_Click() TraitementReponse DoEvents If BonneReponse = 2 Then BDCQuestionSuivante.Visible = True DoEvents Joue "reponseexacte.wav" GagneMillion Else Joue "MauvaiseReponse.wav" Perdu End If End Sub ' Choix du candidat : REPONSE C Private Sub TXTR3_Click() TraitementReponse DoEvents If BonneReponse = 3 Then BDCQuestionSuivante.Visible = True DoEvents Joue "reponseexacte.wav" GagneMillion Else Joue "MauvaiseReponse.wav" Perdu End If End Sub ' Choix du candidat : REPONSE D Private Sub TXTR4_Click() TraitementReponse DoEvents If BonneReponse = 4 Then BDCQuestionSuivante.Visible = True DoEvents Joue "reponseexacte.wav" GagneMillion Else Joue "MauvaiseReponse.wav" Perdu End If End Sub

Les traitements de TXTR1, TXTR2, TXTR3, TXTR4 sont identiques à ceci près que ça commence par If BonneReponse = 1,2,3 ou 4(selon ce qui est indiqué dans la le champ BonneReponse). Comme avant, j'impose un DoEvents pour m'assurer que TraitementReponse se termine avant que la musique ReponseExacte.wav ou MauvaiseReponse.wav ne se joue.

Dans l'exemple actuel (la première question), la bonne réponse est la 3 (Berne). Ainsi, si je clique sur TXTR1, TXTR2 ou TXTR4, If BonneReponse = 3 ne s'exécute pas, et nous nous rendons directement dans le Else (Sinon), et là, je joue le son MauvaiseReponse.Wav (un buzz strident), puis je lance la prodédure Perdu.

Le joueur a choisi la bonne réponse

BDC veut dire Bouton De Commande. Ce préfixe n'est pas obligatoire, mais j'aime bien nommer mes objets de manière à mieux les appréhender.

Concentrons-nous sur TXT3, qui est donc la bonne réponse à cette première question : le champ BonneReponse est effectivement 3. J'affiche alors enfin le bouton vert BDCQuestionSuivante.Visible = True. Son contenu a été initialisé dans la procédure TraitementReponse, vous vous rappelez ?

Effets de bouton en relief

Le sympathique effet dégradé léger de vert, avec petit relief est une possibilité qui existe depuis la version 2007, et qui permet de créer des boutons-fantaisie, un peu moins formels qu'avant.

Procédure en cas de gain d'un million d'euros

Une fois le bouton affiché, j'ajoute encore un DoEvents pour m'assurer que la musique BonneReponse ne va pas se lancer avant d'avoir affiché le bouton. Une fois la musique terminée, j'exécute la procédure GagneMillion, que voici :

VBA
Sub GagneMillion() If VAREchelle = 15 Then VAREchelle = 0 IMG5050.Visible = True IMGCoupDeFilAmi.Visible = True IMGVotePublic.Visible = True DoEvents Joue "GagneMillionFinal.wav" End If End Sub

Cette procédure gère le cas exceptionnel où le joueur a gagné un million d'euros. Ca peut paraître bizarre de se préoccuper de ce cas de figure alors qu'on n'en est qu'à la première question, mais quand on clique sur les différentes réponses, au fur et à mesure de l'avancement du jeu, il viendra peut-être bien un moment ou ce cas va se produire, et il faut donc s'en préoccuper dès maintenant.

Comme vous le voyez, ce code ne s'exécute que If VAREchelle = 15. Or, pour l'instant, VAREchelle est à 1, c'est la valeur de base que je lui ai attribuée dans Form_Open, on a pas encore vu le cas ou cette valeur augmente.

Admettons le joueur vienne de répondre correctement à la 15ème question :

  1. VAREchelle retombe à 0 (Pour recommencer avec un autre candidat par exemple)
  2. Les trois jokers sont tous réaffichés (Visible = True). Ils n'ont peut-être pas été utilisés, mais peu importe : on les réaffiche sans se poser de question.
  3. DoEvents, pour toujours la même raison : Le code VBA doit s'être correctement exécuté jusque-là avant de jouer la musique finale

Nous n'en sommes pas encore au million, loin s'en faut. VBA va donc constater que le If VAREchelle = 15 Then n'est pas vrai, et il va donc se rendre directement sur le End Sub , et revenir sur la ligne qui suit immédiatement l'appel à GagneMillion (Else):

Le joueur a choisi une mauvaise réponse

VBA
Private Sub TXTR1_Click() TraitementReponse DoEvents If BonneReponse = 1 Then BDCQuestionSuivante.Visible = True DoEvents Joue "reponseexacte.wav" GagneMillion Else Joue "MauvaiseReponse.wav" Perdu End If End Sub

Nous arrivons sur l'appel de la procédure Perdu.

Je gère le cas où le joueur clique sur une mauvaise réponse. Il Joue "MauvaiseReponse.wav(Un buzz strident), et il se rend sur la procédure Perdu, que voici :

VBA
Sub Perdu() ' Affichage d'un message idoine selon l'échelle : BDCperdu.Visible = True BDCperdu.Caption = "PERDU ! " Select Case VAREchelle Case Is <= 5: BDCperdu.Caption = BDCperdu.Caption & "Désolé, vous repartez les mains vides." Case Is <= 10: BDCperdu.Caption = "1'500 Euros, c'est mieux que rien !" Case Is <= 15: BDCperdu.Caption = "Mais bon, 48'000 Euros, quand-même !" End Select BDCperdu.Caption = BDCperdu.Caption & Chr(13) & Chr(10) & Chr(13) & Chr(10) & "Cliquez ici pour recommencer avec les questions suivantes" ' Et ensuite, la réinitialisation se fera quand on clique sur le bouton PERDU End Sub

Je commence par afficher le bouton "Perdu" : BDCperdu.Visible = True, et je lui attribue le texte "PERDU !", mais pas seulement, car selon l'état d'avancement du jeu, le candidat ne part pas les mains vides.

Selon le cas (La valeur) de VAREchelle (Qui est toujours à 1, nous n'avons pas encore vu le cas ou cette valeur augmente), si elle est <=5, c'est perdu, si c'est <=10, c'est 1'500€, et si c'est <=15, c'est 48'000€.

Vous pourriez me faire remarquer que dans notre cas (VAREchelle = 1), c'est <= 5, à 10 et à 15. Comment sait-il que si VAREchelle =1, on repart les mains vides ? Parce que le Select Case s'arrête à l'instant où la condition est remplie : ici, on commence par lui dire Case Is <= 5, donc il complète le texte (Caption) du bouton BDCPerdu avec "Désolé, vous repartez les mains vides", et il s'en fiche de savoir si en dessous, il y a d'autres Case qui pourraient convenir, et il fonce droit sur le End Select.

Le petit & que vous voyez un peu partout signifie "Coller", c'est à dire qu'il doit conserver ce qu'il y avait déjà écrit dans le bouton "PERDU !" et y ajouter (&) "Désolé, vous repartez les mains vides".

Et enfin, après le End Select, On ajoute deux sauts de Paragraphe, et on invite le candicat suivant à venir répondre aux questions, comme ceci :

Ensuite, nous atteignons End Sub, et nous revenons directement à la ligne suivant l'appel à Perdu, c'est à dire plus grand chose :

VBA
Private Sub TXTR1_Click() TraitementReponse DoEvents If BonneReponse = 1 Then BDCQuestionSuivante.Visible = True DoEvents Joue "reponseexacte.wav" GagneMillion Else Joue "MauvaiseReponse.wav" Perdu End If End Sub

Clic sur le bouton vert "Prochaine question"

Maintenant, selon que le joueur a choisi la bonne ou une mauvaise réponse, le bouton rouge ou vert est donc affiché sur l'écran.

 

 

Je vais maintenant gérer le bouton vert : que se passe-t-il quand on clique dessus ?

Je commence par faire disparaître ce bouton. Or, on ne peut pas rendre un bouton invisible si on vient de cliquer dessus (S'il est "Actif" en quelque sorte). Il s'agit donc d'"Activer" un autre élément de mon fomulaire pour commencer, mais on ne peut pas "Activer", "Mettre le focus" sur n'importe quoi : il faut qu'il s'agisse d'un bouton ou d'une zone d'édition par exemple.

Or, je ne dispose que d'images ou de zones de texte. Ce que j'ai trouvé de mieux est de créer un petit bouton complètement inutile, qui ne fait rien du tout si on clique dessus, que j'ai intitulé BDCInutile et qui aura pour seule fonction de recevoir le focus (et donc de permettre de quitter le bouton vert pour le rendre invisible).

VBA
Private Sub BDCQuestionSuivante_Click() BDCInutile.SetFocus ' Pour pouvoir ... BDCQuestionSuivante.Visible = False ' ... rendre invisible le bouton sur lequel on est ' Actualisation de l'échelle des gains : VAREchelle = VAREchelle + 1 IMGEchelle.Picture = Application.CurrentProject.Path & "\Echelle" & VAREchelle & ".jpg" DoEvents On Error GoTo RetourPremier ' L'erreur c'est qu'on est sur la dernière question DoCmd.GoToRecord , , acNext Exit Sub RetourPremier: Joue "FinEmission.wav" MsgBox "Toutes les questions ont été posées. On revient à la première question" DoCmd.GoToRecord , , acFirst End Sub

Actualisation de l'échelle des gains

Et voilà *ENFIN* l'endroit où nous augmentons notre variable globale VAREchelle de 1. Jusque là, notre VAREchelle est toujours resté bloquée sur 1, mais maintenant que nous venons de cliquer sur le bouton vert, c'est la preuve que nous avons sélectionné la bonne réponse, et que nous désirons passer à la question suivante.

Affichage dynamique d'une image dans le formulaire

VBA
Private Sub BDCQuestionSuivante_Click() BDCInutile.SetFocus ' Pour pouvoir ... BDCQuestionSuivante.Visible = False ' ... rendre invisible le bouton sur lequel on est ' Actualisation de l'échelle des gains : VAREchelle = VAREchelle + 1 IMGEchelle.Picture = Application.CurrentProject.Path & "\Echelle" & VAREchelle & ".jpg" DoEvents ... End Sub

 

 

 

 

Cette VAREchelle qui vaut maintenant 1 + 1 = 2 va nous servir immédiatement pour modifier dynamiquement l'image de l'échelle, en haut à droite.

Parmi les fichiers que vous avez téléchargé au début de ce didacticiel, il y a 15 fichiers images appelées Echelle1,.jpg, Echelle2.jpg, etc. jusqu'à Echelle15.jpg :

 

 

 

 

 

 

 

 

Je vais donc changer la source de l'image des échelles :

Ensuite, je place un DoEvents pour ne pas qu'il joue la musique de fin d'émission avant d'avoir terminé d'affiché la bonne image d'échelle.

 

Mais pourquoi parle-je de musique de fin d'émission alors qu'on est à peine à la 2ème question ? La musique typique de la fin d'émission ne surgira que lorsqu'on atteint la dernière question du questionnaire (en l'occurrence 28)

Observons le code VBA :

VBA
Private Sub BDCQuestionSuivante_Click() ... ' Actualisation de l'échelle des gains : VAREchelle = VAREchelle + 1 IMGEchelle.Picture = Application.CurrentProject.Path & "\Echelle" & VAREchelle & ".jpg" DoEvents On Error GoTo RetourPremier ' L'erreur c'est qu'on est sur la dernière question DoCmd.GoToRecord , , acNext Exit Sub RetourPremier: Joue "FinEmission.wav" MsgBox "Toutes les questions ont été posées. On revient à la première question" DoCmd.GoToRecord , , acFirst End Sub

Gestion des erreurs (On Error GoTo)

Voyez la ligne On Error GoToRetourPremier. Ca veut dire : "A partir de maintenant, si le code VBA a un problème, tu vas sur l'étiquette RetourPremier":

la ligne d'après (DoCmd.GoToRecord , , acNext) veut simplement dire "Va à l'enregistrement suivant" (Le 2ème, dans notre cas, puisqu'on vient de répondre correctement à la première quetsion)

Comment diable cette commande peut-elle causer un souci à VBA ?

Dans le cas où nous sommes finalement arrivés sur la ... dernière question, et qu'il essaie d'aller sur la acNext (Suivante).

Dans notre cas, pas de problème : on arrive sur la question 2, et tout de suite après, j'écris Exit Sub. Pourquoi dois-je préciser Exit Sub ? Il y a le End Sub un peu plus bas de toute façon ? Eh bien, si je n'écris pasExit Sub, bien qu'il n'y ait pas d'erreur (puisqu'on n'est pas au dernier enregistrement), VBA va continuer a exécuter bêtement le code VBA en dessous de RetourPremier (la musique de fin et les deux autres lignes), ce qui n'est pas souhaitable, évidemment.

Donc, dans le cas ou il n'y a pas d'erreur, on passe simplement à la question suivante, Exit Sub, et bonsoir m'sieur-dames. Mais s'il y a une erreur, c'est à dire qu'il coince sur le acNext parce que nous sommes sur le dernier enregistrement, alors, hop : VBA saute directement par dessus le Exit Sub pour continuer le code qui se trouve sous l'étiquette RetourPremier:, à savoir :

Le cas exceptionnel de la dernière question est ainsi géré.

Clics sur les jokers

L'utilisation des trois jokers est expliqué vers le début de ce didacticiel.

Seul le joker fait vraiment quelque chose au niveau programmation.

Cliquer sur le coup de fil à un amiou sur le vote du public ne fera que déclencher la musique traditionnelle de ces deux jokers.

Le point commun de ces trois jokers est qu'ils disparaissent quand on clique dessus.

Voici la partie commune des trois jokers :

  1. Joue "MusiqueDuJoker.wav"
  2. Dès que la musique est finie : IMGNomDuJoker.Visible = False

Exception pour le : je veux que les deux réponses disparaissent juste avant le son typique, parce que ça ferait bizarre d'entendre d'abord le son, puis seulement à la fin, voir disparaître les deux réponses. Le DoEvents assure, comme d'habitude, que le code VBA soit terminé avant de lancer le son.

VBA
' 50/50 : --------------------------------------------- Private Sub IMG5050_Click() ... Beaucoup de code que nous allons étudier tout à l'heure ... ... IMG5050.Visible = False ' Masquage du joker "50/50" DoEvents Joue "50-50.wav" End Sub ' Coup de fil à un ami : --------------------------------------------- Private Sub IMGCoupDeFilAmi_Click() Joue "CoupDeFilAmi.wav" IMGCoupDeFilAmi.Visible = False ' Masquage du joker "Coup de fil à un ami" End Sub ' Vote du public : --------------------------------------------------- Private Sub IMGVotePublic_Click() Joue "VotePublic.wav" IMGVotePublic.Visible = False ' Masquage du joker "Vote du public" End Sub

Je ne me suis pas lancé dans l'affichage de graphiques en barres qui représenteraient l'avis du public, ou des fichiers wav qui mimeraient une sonnerie de téléphone chez un ami potentiel : c'est très basique.

Fonctionnement du joker 50/50

Comme je vous le disais plus haut, le seul joker qui fonctionne exactement comme dans l'émission originale est le .

La première ligne est Randomize Timer. Un ordinateur est complètement incapable de choisir au hasard. Il doit absolument se baser sur quelque chose qu'il peut calculer, qui ressemble à du hasard (Comme par exemple l'heure qu'il est à la milliseconde près, le temps moyen entre deux pressions sur une touche du clavier, ou ce genre de choses). Si on ne précise pas Randomize Timer, VBA va avoir tendance à répéter les mêmes choix au bout d'un moment (Ce qui peut être intéressant dans certains cas ou on veut retrouver une ancienne séquence au hasard), mais ici, on va le forcer à être plus "aléatoire")

VBA
Private Sub IMG5050_Click() ' Choix de deux réponses fausses au hasard : Randomize Timer ' PREMIERE REPONSE A EXCLURE : ' On choisit au hasard un chiffre entre 1 et 4 : Choix1 = Int(4 * Rnd()) + 1 ...
...
End Sub

Choix1 est une variable que j'ai inventée, qui aurait pu s'appeler Pamplemousse ou Chaise, mais j'utilise Choix1, parce qu'il va s'agir de la première réponse choisie au hasard.

Génération contrôlée de nombres aléatoires avec Rnd()

La fonction Rnd() veut dire "Random" (Hasard), et renvoie un nombre au hasard entre 0 et 1, comme par exemple 0.4575731 ou 0.2997473.

Par exemple, si vous exécutez ce code : MsgBox Rnd(),  il va vous afficher quelque chose du style :

Ensuite, on lui demande de multiplier ce nombre par 4 (4 * Rnd()). Dans notre exemple, ça donnerait : 0.6440821 X 4 = 1.9322463.

On va ainsi obtenir des nombres au hasard parfois très proches de 0 (Par exemple 0.00010211) et parfois très proches de 1 (par exemple 0.9998796)

On va les multiplier par 4 (Dans nos deux cas extrêmes, nous aurions 0.00010211 X 4 = 0.00040844, et 0.9998796 X 4 = 3.9995184).

Nous serons toujours en présence de nombres compliqués, mais toujours compris entre 0.0000000 et 3.9999999.

Fonction Int() (Nombre entier)

Maintenant, nous allons demander d'extraire la partie entière du nombre, grâce à la fonction int() (Entier = Integer en anglais). La partie entière du nombre, c'est le nombre trouvé, mais sans décimale.

Ainsi Msgbox Int(67.997567) affichera "67" (Et pas 68, ce n'est pas un arrondissement)

Ainsi Msgbox Int(4*Rnd()) afficherait 0, 1, 2 ou 3. Vous suivez ?

Nous sommes maintenant les heureux propriétaires d' un nombre au hasard entre 0 et 3, mais ce que nous voulons, c'est un chiffre au hasard entre 1 et 4 ! C'est pourquoi j'ai ajouté 1 au résultat final, comme ceci : Int(4*Rnd())+1

ENFIN, Nous avons ainsi notre chiffre au hasard entre 1 et 4, soiugneusement stocké dans la variable Choix1

Maiiiiiiiis nous ne sommes pas au bout de nos peines !

Boucle While - Wend

Que faire si par malheur, le chiffre choisi au hasard est justement la bonne réponse (Le champ BonneReponse) ? Pas le choix : il faut lui redemander de choisir une réponse entre 1 et 4. Et s'il rechoisit encore par hasard BonneReponse ? C'est pas de chance, mais il faut lui redemander encore une fois.

En fait, il faut lui redemander jusqu'à ce qu'il choisisse une des trois autrees réponses !

VBA
Private Sub IMG5050_Click() ' Choix de deux réponses fausses au hasard : Randomize Timer ' PREMIERE REPONSE A EXCLURE : ' On choisit au hasard un chiffre entre 1 et 4 : Choix1 = Int(4 * Rnd()) + 1 ' Mais si on n'a pas de chance et que la réponse choisie eu hasard est la bonne réponse, ' il faut recommencer à choisir ! En fait, il faut recommencer tant que la réponse choisie ' n'est pas la bonne : While Choix1 = BonneReponse Choix1 = Int(4 * Rnd()) + 1 Wend ... ... ... End Sub

On lui demande donc d'abord de choisir un chiffre entre 1 et 4. Ensuite, Tant que (While) le chiffre choisi est par malheur la bonne réponse, il doit à nouveau choisir un chiffre entre 1 et 4. Même si par vraiment pas de chance, il choisit cent fois la bonne réponse, il bouclera le nombre de fois qu'il faut entre le while et le Wend (WhileEND).

Et si par bonheur, quand il arrive au while, il a déjà choisi une réponse erronée du premier coup ? Eh bien il va directement au Wend sans même rentrer dans le while.

Nous sommes donc certains, à ce stade que Choix1 contient un numéro de mauvaise réponse.

Bien.

Il s'agit maintenant de choisir une 2ème mauvaise réponse : Tout comme Choix1, on lui demande de choisir un chiffre entre 1 et 4

choix2 = Int(4 * Rnd()) + 1

VBA
Private Sub IMG5050_Click() ... ... While Choix1 = BonneReponse Choix1 = Int(4 * Rnd()) + 1 Wend ' DEUXIEME REPONSE A EXCLURE : choix2 = Int(4 * Rnd()) + 1 ' C'est pareil que la première réponse à choisir, sauf que, en plus, il ne faut pas ' non plus que la 2ème réponse choisie ne soit la même que la première : While (choix2 = Choix1) Or (choix2 = BonneReponse) choix2 = Int(4 * Rnd()) + 1 Wend ... ... End Sub

Et, comme dans Choix1, il va falloir boucler/recommencer tant que Choix2 sélectionne par hasard la bonne réponse, mais en plus, il ne faudrait pas que Choix2 soit égal à Choix1... Ce ne serait pas très sympathique pour le candidat de se voir retirer les deux mauvaises réponses C et C par exemple.

C'est pourquoi, il doit recommencer à choisir une réponse au hasard tant que Choix2 = Choix1 ou que Choix2 = BonneReponse.

Ne vous inquiétez pas, ça ne va pas durer une heure, même s'il chooisit 20 fois de suite une réponse insatisfaisante, ça ne durera pas plus de quelques millièmes de seconde.

Maintenant que nous sommes certains d'avoir sélectionné au hasard deux mauvaises réponses différentes, nous allons vérifier desquelles il s'agit, et les masquer : Si la réponse A (1)  a été stockée dans Choix1 ou Choix2 (If (Choix1 = 1) Or (choix2 = 1)), alors on masque la réponse A (TXTR1), avec : TXTR1.Visible = False, et on répète cette vérification pour chacune des 4 réponses :

VBA
Private Sub IMG5050_Click() ... ... While (choix2 = Choix1) Or (choix2 = BonneReponse) choix2 = Int(4 * Rnd()) + 1 Wend ' On masque les deux réponses choisies au hasard : If (Choix1 = 1) Or (choix2 = 1) Then TXTR1.Visible = False If (Choix1 = 2) Or (choix2 = 2) Then TXTR2.Visible = False If (Choix1 = 3) Or (choix2 = 3) Then TXTR3.Visible = False If (Choix1 = 4) Or (choix2 = 4) Then TXTR4.Visible = False Joue "50-50.wav" IMG5050.Visible = False ' Masquage du joker "50/50" End Sub

Il ne reste plus qu'à jouer la musique traditionnelle du , et à masquer le bouton du joker.

VBA
Private Sub IMG5050_Click() ... ... If (Choix1 = 4) Or (choix2 = 4) Then TXTR4.Visible = False Joue "50-50.wav" IMG5050.Visible = False ' Masquage du joker "50/50" End Sub

Code complet du clic sur le joker 50/50

Voici le code complet du bouton

VBA
Private Sub IMG5050_Click() ' Choix de deux réponses fausses au hasard : Randomize Timer ' PREMIERE REPONSE A EXCLURE : ' On choisit au hasard un chiffre entre 1 et 4 : Choix1 = Int(4 * Rnd()) + 1 ' Mais si on n'a pas de chance et que la réponse choisie eu hasard est la bonne réponse, ' il faut recommencer à choisir ! En fait, il faut recommencer tant que la réponse choisie ' n'est pas la bonne : While Choix1 = BonneReponse Choix1 = Int(4 * Rnd()) + 1 Wend ' DEUXIEME REPONSE A EXCLURE : choix2 = Int(4 * Rnd()) + 1 ' C'est pareil que la première réponse à chosiir, sauf que, en plus, il ne faut pas ' non plus que la 2ème réponse choisie ne soit la même que la première : While (choix2 = Choix1) Or (choix2 = BonneReponse) choix2 = Int(4 * Rnd()) + 1 Wend ' On masque les deux réponses choisies au hasard : If (Choix1 = 1) Or (choix2 = 1) Then TXTR1.Visible = False If (Choix1 = 2) Or (choix2 = 2) Then TXTR2.Visible = False If (Choix1 = 3) Or (choix2 = 3) Then TXTR3.Visible = False If (Choix1 = 4) Or (choix2 = 4) Then TXTR4.Visible = False Joue "50-50.wav" IMG5050.Visible = False ' Masquage du joker "50/50" End Sub

Idées d'améliorations possible du programme

Nous voici arrivés à la fin de ce didacticiel. Parmi les différentes améliorations possibles à ajouter au programme, notons celles-ci .