Chess VBA a de la classe

A l’abordage pas à pas de la classe Board : Class_Initialize()

A l’abordage pas à pas de la classe Board : Class_Initialize()


Embarquement immédiat en 1ere classe Board. Dans cette session de mise au point (debug),

on abordera pas à pas comment créer les 64 cases de l’échiquier, les deux joueurs et leurs pièces.

Quand Chess VBA a de la classe !

Cliquez dans la fenêtre projet du VBE sur le module de classe Board.

La fenêtre d’édition présente le code de Board.

Dans le corps de la 1ere procédure Class_Initialize(), cliquez dans la marge (voir Mise au point avec le débogueur VBA) pour placer un point d’arrêt juste après la création d’une nouvelle case sur l’affectation de n° de case :

sqr.Ordinal = ordSqr
Point d'arrêt (breakpoint) dans Class_Initialize() de Board et la contante hexa &H88

Dans la fenêtre d’Exécution immédiate (Ctrl+G), copier-coller et valider par ENTER l’instruction suivante :

Set boardMain = New Board

La ligne du sqr.Ordinal = ordSqr de Class_Initialize() devient jaune.

L’ordinal de la case ordSqr = 68 = &H44 = a1 est l’index de la première case de l’échiquier.

On a entrevu dans VBA & l’échiquier 0x88 et surtout dans Test hors rangée avec l’échiquier &H88 que pour savoir si une case est valide, on teste si la différence de l’ordinal avec a1 AND le masque &H88 est nul, autrement dit si la case se trouve dans l’échiquier centré sur le tableau de 256 éléments. Comme a1 est une case valide, on se retrouve dans la partie Else.

Avançons pas à pas avec le bouton "Pas à pas principal" (Shift+F8) [Step Over] de la barre d’outil de mise au point. On a sauvé ordSqr dans la propriété Ordinal de la case. La ligne jaune devient :

Set m_arrSquare(ordSqr) = sqr

Cette affectation sauvegarde l’objet case sqr dans le tableau des cases indexé par l’ordinal ordSqr.

Si ce n’est pas déjà fait, ouvrir la fenêtre des Variables Locales

VBE menu "Afficher" > "Fenêtre Locale" (Locals Window)

Vous devez y voir la variable locale ordSqr = 68

Pressez F5 sept fois en surveillant la fenêtre des Variables Locales jusqu’à atteindre la valeur ordSqr = 75 c-a-d l’ordinal de la case h1.


Si après avoir appuyé plusieurs fois sur F5, vous ne voyez plus d’instruction en jaune, c’est que le point d’arrêt n’a pas été placé correctement dans la partie Else du If ou que vous avez tapé un F5 de trop soit huit F5 à la place de sept. Dans ce cas, toute l’initialisation est déjà terminée. Pour la recommencer, vous devez libérer l’échiquier par :

Set boardMain = Nothing

Puis recommencer depuis le début de la session de mise au point.


Case en dehors de l’échiquier

On continue en pas à pas principal avec Shift+F8 [Step Over].

Après le Next, on boucle (on revient au début du For) avec la valeur suivante de l’ordinal, soit 76 = h1 + 1. Attention h1 + 1 n’est pas a2 !

Cette fois-ci la condition case hors échiquier du If devient True et on entre dans la partie Then avec un F8.

Set m_arrSquare(ordSqr) = Nothing

On ne crée pas les cases en dehors de l’échiquier.

Sur les 256 cases de l’échiquier 0x88, on créera juste les 64 cases qu’il nous faut.

Toutes les autres seront initialisées à Nothing, c-a-d qu’elles ne prennent presque rien en place mémoire !


Création du joueur des Blancs

Pour sauter la création des autres cases, placer un point d’arrêt après le Next sur :

Set m_playerWhite = New Player

Supprimer le point d’arrêt dans le Else en cliquant sur son point rouge dans la marge.

Lancer un Run (F5) afin de s’arrêter sur la ligne de la création du joueur des Blancs.

Cliquez sur F8. Le pas à pas détaillé [Step Into] permet de poursuivre le pas à pas à l’intérieur de la procédure s’il s’agit d’un appel de procédure ou de Class_Initialize() si c’est la création d’un objet par New. Le débogueur automatiquement ouvre le module de classe Player et s’arrête sur le Class_Initialize() de Player.

Avancer en pas à pas avec trois F8.

L’initialisation est beaucoup plus courte. On crée les collections des pièces et des captures avec New mais ces collections sont encore vides.

  • Soit on continue en pas à pas avec des F8 y compris sur le End Sub de Class_Initialize() de Player.
  • Soit on sort directement par un "Pas à pas sortant" (Ctrl+Shift+F8) [Step Out].

On est sorti du Class_Initialize() de Player et on se retrouve à nouveau dans le Class_Initialize() de Board sur la création du joueur des Noirs.

Comme on a déjà vu la courte initialisation du joueur des Blancs, on saute celle des Noirs par :

"Pas à pas principal" (Shift+F8) [Step Over].

Avancez-en par deux Shift+F8 (pas à pas principal) pour sauter les deux SetOpponent() qui permettent de retrouver l’adversaire à partir d’un joueur donné en sauvegardant PlayerWhite dans la propriété Opponent de PlayerBlack et réciproquement.


Création des pièces avec le constructeur BuildPlayer

Une autre façon d’avancer plus vite qu’en pas à pas serait d’utiliser le dernier bouton de la barre de Debug : "Avancer jusqu’au curseur" (Step To Cursor) ou le menu "Run to Cursor" (Ctrl+F8).

Cela évite d’ajouter un nouveau point d’arrêt puis un Run (F5) mais il faut bien sûr que le curseur d’édition de texte soit sur la ligne voulue, c-a-d ici la création des pièces du joueur des Blancs.

La double ligne suivante devient jaune :

m_playerWhite.BuildPlayer True, Me, 16, 32, _
        pawnWhiteAttackRightOffset, pawnWhiteAttackLeftOffset

Normalement cela aurait du être au Class_Initialize() de Player de créer les pièces.

Le problème est qu’on ne peut pas en VBA passer des paramètres à Class_Initialize() or on a voulu factoriser la création des pièces indépendamment de la couleur.

C’est pourquoi on a créé la procédure BuildPlayer() qui accepte de nombreux paramètres. On parle de constructeur paramétré de l’objet Player. Au moins pour le joueur des Blancs, cela mérite d’avancer en "Pas à pas détaillé" (F8) [Step Into].


Me et la notion de parent

Notons que lors de l’appel de BuildPlayer(), le second paramètre est Me (moi), c-a-d moi l’objet de classe Board.

Si vous regardez la fenêtre des Variables Locales dans la capture d’écran du début d’article, vous y verrez dans la 1ere colonne Expression Me sur la même ligne que le Type Board en dernière colonne. Les curieux cliqueront sur le petit "+" devant Me afin d’explorer toutes constantes, variables Private et interface Public de la classe Board.

On va établir une relation de parenté entre les deux objets Board et Player.

Board est parent de Player, mais Board et Player sont des types c-a-d des noms de classe abstrait tandis que Me représente l’objet concret de type Board qui a été créé en mémoire par New.

Attention toutefois à la portée de l’objet Me.

Me dans la classe Board représente l’objet Board créé par New.

Si on utilisait Me dans une autre classe, il représenterait l’objet de cette autre classe.

Public Sub BuildPlayer(ByVal isWhite As Boolean, parent As Board, _

Le deuxième paramètre du constructeur BuildPlayer() a été justement appelé parent et il est de type Board. On range ce paramètre dans le champ Private m_board de la classe Player.

  • A l’intérieur de la classe, on a le droit de modifier les champs Private comme m_board. Un champ en lecture seul est généralement initialisé dans Class_Initialize() ou dans un constructeur avec paramètres tel que BuildPlayer().
  • Si l’utilisateur de la classe veut remonter à l’objet Board à partir de PlayerWhite ou PlayerBlack, il ne pourra utiliser que l’interface Public BoardChess() qui est en lecture seule (Get sans Let) car un joueur ne peut pas changer de Board. Cela garantit l’intégrité de la relation parent / enfant entre Board et Player.

Régler vos pas à pas

Vous pouvez choisir d’avancer en pas à pas détaillé (F8) [Step Into] ou principal (Shift+F8) [Step Over] selon que vous voulez étudier en profondeur telle création de pièce telle que le Roi puis sauter les autres pièces car le mécanisme est identique.

Vous pouvez aussi sortir de BuildPlayer() par un "Pas à pas sortant" (Ctrl+Shift+F8) [Step Out].

Vous pouvez finalement sortir complètement du Class_Initialize() de Board par un Run (F5).


Les Tours sur la grande diagonale

On est complètement sorti de la session de mise au point. On a donc la main pour saisir de nouvelles commandes dans la fenêtre d’Exécution immédiate.

Vérifions qu’il y a bien une Tour Blanche en a1 et une Noire en h8.

? Not boardMain.GetRook(a1, True) Is Nothing

True

? Not boardMain.GetRook(h8, False) Is Nothing

True


Libérez l’échiquier

De la même façon que l’on a créé l’échiquier par un New Board, il est recommandé d’effacer toutes les pièces, joueurs et cases par :

boardMain.FreeBoard

Puis de libérer l’échiquier de la mémoire avec Nothing.

Set boardMain = Nothing

Précédent : Architecture échiquéenne VBA orientée objet

Suivant : Le déplacement du cavalier en VBA

Posté le 25 juillet 2011 par Matt