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 23 mars 2010

Boules (P)03/2010 MyLzz59

(Rubrique VB-VBA)

0) Intro

Il y a quelques jours, notre Miss me faisait remarquer qu'il y avait longtemps que je ne lui avais pas conçu de programme.. Il n'en fallait pas plus pour titiller la "pianiste" que je suis, et je me suis mise en quête d'une idée de petit jeu susceptible d'intéresser la Miss, avec pour autre contrainte son développement en VBA sous Word ou Excel.

Tss.. J'entends d'ici les critiques et quolibets d'autres "vrais pianistes" (ou se définissant comme tels): "Visual Basic, elle.. Ben voyons, c'est un langage antédiluvien qui date d'au moins ..une décennie () ! De nos jours on développe en Java J-Truc-Truc-Machin-Chose version quarante-douze point kêk-chose aussi.. ou au pire en Dot Net 10, ma bonne dame !" Re-Tss..

Ben oui, mon langage préféré a toujours été le BASIC, et la version que j'affectionne est Visual Basic 6, la dernière non-dot-net. Certes, entre temps, 4 nouvelles versions de Basic "Dot Net" ont vu le jour, et l'on pourrait croire VB6 définitivement mort et enterré. C'est vrai et c'est faux. VB6 en tant que langage autonome l'est, Microsoft n'en assurant même plus le suivi depuis lurette, mais VB6 a "enfanté" deux ersatz toujours en vie, VBA (Visual Basic pour Applications), et VBS (VB Script). VBS est plutôt dédié personnalisations de machines, il n'a pas d'environnement éditeur, pas de débogueur (correcteur), ses programmes s'écrivent directement dans des fichiers texte non compilés, on ne peut y créer de réelle interface, etc..

Venons-en à VBA. VBA dispose d'un environnement éditeur assez semblable à (feu) VB6, il sait créer des fenêtres Windows, dispose d'un puissant débogueur, celui qu'avait VB6, et permet prendre un contrôle quasi total sur ses hôtes, à l'intérieur desquels il est "caché". VBA "habite", peut-être encore à votre insu, dans des logiciels que vous utilisez probablement couramment au travail, à savoir la suite Office (Word, Excel, Powerpoint, Access..) et quelques produits tiers ayant acheté la licence (Crystal Reports..) VBA est faussement appelé "éditeur de macros", dont il a pris la succession depuis Office 97, existe toujours dans Office 2007 (PC), est réintégré dans Office 2008 (Mac), et devrait cohabiter en standard avec une version optionnelle dérivée de VB.Net dans Office 2010 (à confirmer). Bref..

1) Le Jeu

Peut-être connaissez-vous ce jeu, assez répandu sur les pda et gsm, où il faut supprimer judicieusement des boules empilées, lorsqu'elles sont au minimum trois jointives de même couleur, afin d'en garder en fin de partie le moins possible ? Voici donc le jeu retenu. Un jeu de logique et de hasard, prenant, et somme toute simple à programmer

L'hôte qui se prête le mieux à cette réalisation est Excel, car il gère déjà un empilement ..de cellules Dans ma réalisation, à la place de boules (ce serait cependant aisément modifiable, qui s'y colle ?) j'ai opté pour des cases colorées. Une aire de jeu de 40 colonnes sur 30 lignes, et une barre d'état au-dessous, le tout dans une feuille d'Excel.


Nous allons d'abord planter le décor (o gué, o gué ). Alors que le reste de la feuille est caché, l'aire de jeu s'installe dans la partie fixe des volets. La taille d'une cellule de jeu est de 20x19 pixels. Le choix des couleurs le rend compatible avec les versions d'Excel antérieures à 2007. Afin de vous ôter vos complexes (o gué, o gué ) cette chiante pénible tâche qui d'ailleurs n'apporte rien sur le plan technique (sauf peut-être de chercher dans 2007 où ils ont planqué les fonctions que vous connaissiez ), je vous ai concocté un bout de code qui bâtit l'interface pour vous. Allez le récupérer ICI, démarrez Excel avec un classeur vierge, appelez l'éditeur VBA (Alt-F11 ), double-cliquez dans l'Explorateur de Projets VBA (menu Affichage, s'il n'est pas présent) sur la première Feuille du classeur, collez-y le bout de code, et exécutez-le (l'icône Triangle, ou la touche F5 ). Sauvegardez votre classeur au format ".xls" ou ".xlsM" mais surtout pas ".xlsX" !!


Si vous avez obtenu l'équivalent de l'image ci-dessus, alors tout va bien, vous pouvez vous débarrasser du bout de code, il ne servira plus..

2) Remplir l'Aire de Jeu

a] Pour faciliter le redimensionnement éventuel du jeu et éviter les redites, commençons par définir une série de constantes, en Zone Déclarations afin de les rendre accessibles de toutes les procédures à venir:

* Tit = "Boules (P)03/2010 MyLzz59" => le titre du jeu
* Ym = 30, Xm = 40 => la taille (lignes, colonnes) de l'aire de jeu
* Nm = 900 => la quantité de boules au départ, arbitraire à 3/4 de l'aire
* Xt = 2 => abscisse de la cellule fusionnée du titre
* Xb = 18 => abscisse de la cellule fusionnée du nombre de pions restants
* Xc = 27 => abscisse de la cellule fusionnée du nombre de coups joués
* Xr = 32 => abscisse de la cellule fusionnée du pseudo-bouton "Recommencer"

' -----------------
' Zone Déclarations
' -----------------
Const Tit = "Boules (P)03/2010 MyLzz59"
Const Ym = 30, Xm = 40, Nm = 900, Xt = 2, Xb = 18, Xc = 27, Xr = 32
b] Nettoyage de l'Aire de Jeu: remplissons le fond des cases par un gris moyen (Interior.ColorIndex=15), et effaçons-en l'éventuel contenu texte (ClearContents). Ecrivons également en ligne d'état le titre (Tit), le nombre de boules (Nm=900), et le nombre de coups joués (zéro).

Notez au passage que la feuille est protégée (sans mot de passe) afin de ne permetre aucune modification (volontaire ou non) de l'utilisateur(trice), qui ne peut que sélectionner les cellules, toutes verrouillées..

c] La boucle de remplissage. Un tableau P(1 To Xm) de 40 nombres entiers est destiné à mémoriser combien de boules ont déjà été mises dans chacune des 40 colonnes de l'aire, afin de ne pas les remplir (aléatoirement) au-delà de leur capacité (Ym=30). La boucle (For T=) effectue les Nm (=900) placements, pour chaque l'on tire une colonne aléatoire (X=Int(Rnd*Xm)+1) entre 1 et 40 jusqu'à en trouver une qui ne soit déjà remplie (Loop While). Dans cette colonne X, à la bonne altitude (Ym-P(X)) l'on colorie la case aléatoirement (Interior.ColorIndex=Int(Rnd*4)+3) avec l'une des 4 couleurs suivantes: rouge (ColorIndex=3), vert (ColorIndex=4), bleu (ColorIndex=5), ou jaune (ColorIndex=6). Pensez à incrémenter P(X)
' -------------------------
' Crée un Nouvel Empilement
' -------------------------
Sub Remplis()
Dim P(1 To Xm) As Integer
Randomize Timer
Sheets(1).Unprotect ""
Range(Cells(1, 1), Cells(Ym, Xm)).Interior.ColorIndex = 15
Range(Cells(1, 1), Cells(Ym, Xm)).ClearContents
For T = 1 To Nm
Do: X = Int(Rnd * Xm) + 1: Loop While P(X) = Ym
Cells(Ym - P(X), X).Interior.ColorIndex = Int(Rnd * 4) + 3
P(X) = P(X) + 1
Next T
Cells(Ym + 2, Xt).Value = Tit
Cells(Ym + 2, Xb).Value = Nm: Cells(Ym + 2, Xc).Value = 0
Sheets(1).Protect ""
End Sub
Vous pouvez d'ores et déjà tester le remplissage depuis l'éditeur VBA: collez la Zone Déclarations et le Sub Remplis dans la première feuille (la seule restante) du classeur (dans VBA ), sauvegardez, cliquez n'importe où entre "Sub Remplis" et son "End Sub", puis exécutez le code.

3) Comment l'utilisateur(trice) joue..

Le plus facile, c'est de le(la) faire double-cliquer sur une cellule. Le double-clic élimine la possibilité d'une sélection multiple. VBA gère la récupération du double-clic au travers d'une procédure dite "événementielle", nommée "_BeforeDoubleClick", dont la syntaxe est imposée. Utilisez les deux zones déroulantes au-dessus du code pour la générer. Ce corps de procédure vous fournit (Target) la cellule visée (inutilisée ici), ainsi qu'un moyen de bloquer la fonction automatique d'Excel (l'édition du texte) associée au double-clic d'une cellule: forcer Cancel à Vrai (True)

Nous ne mettrons dans cet événement que l'appel de la procédure d'identification de la forme (voir ci-après), et le "Cancel=True"..

Rem: le ":" en début de ligne est indispensable, sinon VBA confondrait "Forme" avec une étiquette de ligne, vu que le Sub Forme n'a pas de paramètre !!
' -------------------------------------
' EVT: Supprime la Forme Double-Cliquée
' -------------------------------------
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
: Forme: Cancel = True
End Sub
4) Détecter la forme visée par l'utilisateur(trice)

Ce(tte) dernier(ère) a double-cliqué dans une cellule, dont on récupère les coordonnées ligne (ActiveCell.Row) et colonne (ActiveCell.Column). Cette cellule peut appartenir aux éléments suivants: une boule (son code couleur est compris entre 3 et 6), le fond de l'aire est frais (code couleur 15), des zones non fonctionnelles de la ligne d'état, ou la cellule fusionnée "Recommencer" (ligne 32=Ym+2, colonne Xr=32). Dans deux des cas il n'y a rien à faire, s'il s'agit d'une boule il faut détecter et supprimer la forme si elle convient (est constituée d'au moins 3 boules), ou appeler le sub Remplis si c'est le pseudo-bouton "Recommencer".

a] Principe de détection (attention, c'est là le point compliqué )

Définissons un compteur numérique, initialisé à zéro. Créons une procédure "Tagge" à laquelle on passe les coordonnées X et Y de la cellule visée, ainsi que notre compteur. Si la cellule est dans l'aire, contient un code couleur associé à une boule (que l'on mémorise temporairement dans Static C), et n'a pas été marquée d'un texte, marquons-la du texte "*" (pour ne pas la compter plusieurs fois), et incrémentons notre compteur N de 1.

Procédons de même pour les 4 cellules adjacentes (dessus, dessous, gauche, et droite), en ..invoquant de façon récursive notre procédure Tagge () Chaque fois que le même code couleur (C) sera trouvé dans l'une de ces 4 cellules, elle sera marquée d'une "*", N sera incrémenté, et ..on retente les 4 cellules adjacentes à celle-ci Si elle est au centre d'une croix, une même cellule sera donc vérifiée 5 fois, d'où l'intérêt (n°1) du marquage

Notez que ce procédé (récursivité) se retrouve par exemple dans le jeu du Démineur ("ouverture" des zones de zéro bombe), ou dans le calcul mathématique "cas d'école" de la Factorielle

Au sortir de ces appels récursifs, notre compteur N reporte la quantité de cellules marquées d'une "*". Si elle est supérieure ou égale à 3, nous allons lancer une procédure de suppression de la forme (ainsi que mettre à jour les compteurs de boules et de coups joués), sinon juste effacer les marquages (sans incrémenter le compteur de coups )

b] Le pseudo-bouton "Recommencer"

Nous allons nous occuper de lui par la même occasion, via la même procédure "Tagge", qui renverra alors N=-1 sans tenter de récursivité. Au sortir de l'appel de "Tagge", l'on testera donc 3 cas: (N>=3) suppression de la forme, puis (N>-1) effacement des "*", sinon ne rien faire (l'appel de "Remplis" est déjà dans "Tagge", au bout d'une question de confirmation (If MsgBox()) ).

Notez que "Forme" (tout comme "Remplis") ôte puis remet la protection de la feuille..
' ------------------------
' Traite la Forme Désignée
' ------------------------
Sub Forme()
Dim N As Integer
Sheets(1).Unprotect ""
N = 0: Tagge ActiveCell.Row, ActiveCell.Column, N: DoEvents
If N >= 3 Then
Cells(Ym + 2, Xb).Value = Cells(Ym + 2, Xb).Value - N
Cells(Ym + 2, Xc).Value = Cells(Ym + 2, Xc).Value + 1: Supprime
Else
If N > -1 Then Range(Cells(1, 1), Cells(Ym, Xm)).ClearContents
End If
Range("A1").Select: DoEvents
Sheets(1).Protect ""
End Sub

' -------------------
' (utilisé par Forme)
' -------------------
Sub Tagge(ByVal Y As Integer, ByVal X As Integer, ByRef N As Integer)
If X < 1 Or X > Xm Or Y < 1 Or (Y > Ym And Y <> Ym + 2) Then Exit Sub
If Y = Ym + 2 Then
' Menu
N = -1: If X = Xr Then If MsgBox("Réinitialiser l'Aire de Jeu ?", _
vbQuestion + vbYesNo + vbDefaultButton2, Tit) = vbYes Then Remplis
Else
' Zone de Jeu
Static C
With Cells(Y, X)
If N = 0 Then C = .Interior.ColorIndex: If C > 8 Then Exit Sub
If .Text = "" And .Interior.ColorIndex = C Then
.Value = "*": N = N + 1
For T2 = Y - 1 To Y + 1 Step 2: Tagge T2, X, N: Next T2
For T1 = X - 1 To X + 1 Step 2: Tagge Y, T1, N: Next T1
End If
End With
End If
End Sub
5) Suppression de la forme

Celle-ci a lieu en deux temps: d'abord nous allons scanner chaque colonne à la recherche d'une "*". S'il y en a une, nous allons effectuer un couper-coller de la zone d'aire située au-dessus d'elle, afin de la descendre d'une ligne, ce qui "écrase" la boule marquée. Pensez à réinitialiser la cellule tout en haut (ligne 1) en "fond" (ColorIndex=15 et pas de texte). Pensez aussi à retester l'emplacement où était la boule supprimée

Puis, une fois la colonne traitée, l'on teste si elle contient encore une boule (tout en bas ). Si elle est vide, on procède par un couper-coller similaire pour décaler les colonnes de droite, et l'on réinitialise la dernière, tout à droite. Pensez à retester la position de la colonne vide, après de décalage, sauf si elle est de nouveau vide (plus de colonnes).
' ------------------------
' Supprime la Forme Taggée
' ------------------------
Sub Supprime()
For X = 1 To Xm
' Colonne
For Y = Ym To 1 Step -1
If Cells(Y, X).Text <> "" Then
If Y > 1 Then
Range(Cells(1, X), Cells(Y - 1, X)).Copy
Range(Cells(2, X), Cells(Y, X)).PasteSpecial xlPasteAll
End If
Cells(1, X).Interior.ColorIndex = 15
Cells(1, X).Value = "": Y = Y + 1
End If
Next Y
' Ligne
If X < Xm And Cells(Ym, X).Interior.ColorIndex = 15 Then
Range(Cells(1, X + 1), Cells(Ym, Xm)).Copy
Range(Cells(1, X), Cells(Ym, Xm - 1)).PasteSpecial xlPasteAll
Range(Cells(1, Xm), Cells(Ym, Xm)).Interior.ColorIndex = 15
Range(Cells(1, Xm), Cells(Ym, Xm)).ClearContents
If Cells(Ym, X).Interior.ColorIndex <> 15 Then X = X - 1
End If
Next X
End Sub
Le Code Complet de ce Jeu est disponible ICI..

-MyLzz59-

4 Commentaire(s):

Stéphane a dit…
:'(
j ai pas encore tout lu! (manque de temps pour tout en ce moment :p)

...tu m arretes si je dis une connerie (façon Barthez dans les guignols!) mais ça m a l air touffu! nan?!

allez à plus et ne t inquiete pas, je tacherai de le mettre en place... si si (Taz en mode tétu)
D'ailleurs je crois que Delph' aussi, (rapport à son temps libre desormais, ;) )

Bizes à vous deux, je me sauve... :*
Stéphane a dit…
:p
mais par quoi commencer, mon admiration ou mon dépit....
J ai tout d abord réussi à installer le jeu...non sans difficulté, malgré le flot d explication, ;) ... j ai tout lu et j ai tout ..."pas compris"!!! ben oui...
j ai fait une partie, ou comme de bien entendu, j ai fait un score minable! mais là n est pas mon dépit! il vient du fait qu au fur et à mesure que je jouais, je me me disais: mais comment à t elle fait pour résoudre ça et puis ça et ainsi de suite? je ne parle pas du langage, hein, trop abscons pour moi, non non , simplement le cheminement...:p... et d'où mon admiration!!!!
Tu vas me dire: tout est écrit... ben tiens! et moi de te répondre: vi vi j ai tout lu :D
bon, pour finir, ben le jeu, y march' pû! j ai du cafouiller lors de la fermeture...mais je remettrai le nez asap...
Bisous Mylène et merci!
:*
MyLzz59 a dit…
Ben moi ce sera mon admiration, Taz, pour t'y être collé courageusement :*

J'ai dit, écrit, et je maintiens que ce code est simple, excepté une unique difficulté, la notion de récursivité. C'est elle qui permet la détection aisée des formes quelles qu'elles soient ;)

Mais j'ai déjà prévu d'en reparler, à l'occasion du prochain programme (finalisé, article en cours de rédaction) :) car lui aussi utilise de la récursivité, et ..quasiment la même feuille interface excel :P

A part ça, le déroulement du jeu, vu du code, est purement répétitif: l'utilisateur(trice) double-clique sur une forme, on la détermine, compte ses cases, et si elles sont au moins trois on supprime la forme. Rien d'autre :)

Promis, je répondrai à toutes tes questions, Taz :*

-MyLzz59-
Stéphane a dit…
;)
tu inverses les rôles, Mylène!
Moi, je n ai qu'à suivre tes indications... et j ai 2-3 bases que m a appris une amie... ;-) ça sert bien! :*

je ne m y suis pas encore remis..j ai effectivement un bogue, on en reparlera...
Bisous Miss