Architecture échiquéenne VBA orientée objet

Conception objet du jeu d’Echecs : Class module .cls

Conception objet du jeu d’Echecs : Class module .cls


Cette étape déterminante marque une avancée majeure dans le développement du projet de jeu d’Echecs en VBA. L’ensemble du code source de l’approche dynamique orientée objet de l’architecture est attaché en pièce jointe zippée (2540 lignes de code VBA en 201 procédures). Préparez-vous à l’ascension du col du Galibier (2645 m) !

Importer les fichiers VBA joints

Vous pouvez archiver Chess.xls en Chess02.xls : voir Gestion de la sauvegarde du .xls et de ses modules .bas

Dans le VBE de Chess.xls, effacez les modules ModChess et ModBoard.

Il ne reste donc que l’échiquier graphique dans la feuille de calcul sans aucun code VBA.

Pour éviter de devoir copier-coller des quantités importantes de code VBA, vous trouverez le document joint ChessVba03.zip (19 Ko) contenant 3 modules .bas et 5 modules de classe .cls dans le répertoire Source03. La feuille Excel Chess03.xls n’est pas fournie.

ChessVba03.zip

Comme après tout téléchargement sur Internet, passez systématiquement l’anti-virus avant et après le dézip surtout pour les .xls mais également pour les fichiers textes .bas et .cls (même si bien évidemment il n’y a pas de virus). Le gestionnaire de fichiers de Windows Vista ou Seven est capable de déziper un .zip sinon vous pouvez utiliser l’utilitaire freeware 7-zip.

Dans la fenêtre de projet du VBE, importez les modules .bas et les modules de classe .cls

VBE menu "Fichier" > "Importer fichier" (Ctrl+M)

Une fois tous les fichiers VBA importés, vous pouvez archiver Chess.xls en Chess03.xls


Architecture du jeu d’Echecs : approche dynamique

Les cinq objets du jeu d'Echecs

On a complété la conception du projet en ajoutant l’objet Move (coup) qui interagit avec les autres objets Board, Square, Player et Piece précédemment abordés.

On notera la flèche bidirectionnelle entre Square et Piece montrant que l’on a résolu le problème de référence en avant de l’approche statique.


1 objet = 1 Class module .cls

A chaque type défini par l’utilisateur dans l’ancien ModBoard correspond maintenant un module de classe .cls

Le nom de la classe est le type de l’objet. Quand on utilise une classe, son nom apparaîtra dans la déclaration d’une variable après le mot-clé As exactement comme un type défini par l’utilisateur mais également après l’opérateur New pour créer l’objet.

Dans un Class Module .cls, on ne peut déclarer qu’une classe. Elle est composée de deux parties :

  • L’interface qui définit les Function, Sub et Property Public. C’est la face visible de l’iceberg de la classe. L’interface est le contrat qui permet d’utiliser la classe.
  • L’implémentation est la face cachée Private de l’iceberg de la classe. On retrouve quasiment les mêmes champs qu’avec l’ancien type correspondant défini par l’utilisateur dans ModBoard. Pour chaque champ de la classe, on a ajouté le préfixe "m_" signifiant Membre de la classe.
Interdépendance entre les classes Board, Square et Piece

La différence entre les types définis par l’utilisateur et la Programmation Orientée Objet (POO), est qu’avec la POO, il n’y a plus de problème de référence en avant :

  • Sur une case, on peut mettre une pièce. Pour une case vide, son champ Piece est Nothing.
  • Une pièce est sur une case. Après une capture son champ Square devient Nothing.
Champ Private pour l'implémentation et Property Public ordinal de l'interface de Square

Contrairement au champ d’un type défini par l’utilisateur, le champ d’une classe tel que m_ordinal est généralement Private. Cela veut dire qu’il faut passer par l’interface Public Ordinal pour lire ou écrire ce champ. On parlera alors de Property (propriété) de la classe en lecture (Get) ou écriture (Let).

boardMain.playerWhite.isWhite = True

Contrairement à une méthode Sub ou Function, une Property en écriture comme isWhite peut apparaître à gauche du signe "=" en tant que cible d’une affectation.

Méthodes et propriétés Public de l'interface des classes

La séparation entre interface Public et implémentation Private permet au développeur de la classe de faire évoluer l’implémentation de la classe sans impacter les autres modules. S’il garantit que l’interface (le contrat) n’a pas changé, alors l’utilisateur de la classe n’a pas à adapter l’appel des méthodes et propriétés de la classe.

L’utilisation de la classe ne se faisant que via l’interface Public, le développeur de la classe est sûr qu’il n’y aura pas de modification sauvage comme cela est possible avec des variables globales où n’importe qui peut les modifier n’importe où. On peut identifier qui appelle une classe en mettant un point d’arrêt dans l’interface Public.

La POO a un coût. L’accès à la classe via son interface est légèrement moins performant qu’un accès direct à des variables globales en programmation procédurale. Cependant la POO permet de développer plus vite un code structuré, réutilisable plus compréhensible. Si vous programmez en langage assembleur de bas niveau, le code sera plus rapide qu’avec un langage de haut niveau comme C, C++ ou VBA, cependant il faudra beaucoup plus de temps pour le développer.


Les modules .bas

ModFen.bas servira ultérieurement pour gérer le format FEN.

Pour le moment la Sub SetBoardPosition() est déclarée mais ne fait rien.

ModPgn.bas permettra de lire un fichier de partie au format .pgn

Pour l’instant, on n’a mis que les constantes qui peuvent être utilisées ailleurs.

ModChess.bas comprend toutes les constantes déjà vues précédemment et de nouvelles.

On y trouve également les fonctions de conversion ainsi que la nouvelle version d’affichage de l’échiquier GuiDisplayBoardAt() non plus avec l’échiquier sous forme de String retournée par BoardBuild() mais avec l’objet échiquier boardMain As Board passé comme paramètre.

Ce dernier est déclaré comme variable globale Public en fin de module.

Public boardMain As Board
Public isFrench As Boolean

Créons l’objet échiquier

Dans la fenêtre d’Exécution immédiate :

? boardMain is nothing

True

La variable globale boardMain n’est pas encore créée.

Il est préférable de saisir chaque instruction plutôt que de faire un copier-coller pour expérimenter l’autocomplétion et les info-bulles car le type de classe Board est maintenant connu par le VBE.

Set boardMain = New Board

Rien ne s’affiche mais il s’en est passé des choses !

? boardMain is nothing

False

C’est le feu vert pour utiliser l’échiquier boardMain.

? boardMain.playerWhite.ListPiece.Count

16

Il y a bien 16 pièces côté Blanc !

? boardMain.playerWhite.ListPiece(1).Name

K

Voici le Roi en tête de la collection. Sur quelle case se trouve-t-il ?

? boardMain.playerWhite.ListPiece(1).Square.Name

e1

isFrench = True

On a basculé la langue d’affichage de l’anglais au français.

? boardMain.playerWhite.ListPiece(1).Name

R

L’initiale du Roi s’affiche maintenant en français.

Vous pouvez également explorer les autres pièces des Blancs ou des Noirs.


Affichons l’objet échiquier sur le GUI

Dans la feuille de calcul, sélectionnez l’échiquier R2C14 à R9C21 puis pressez DEL pour effacer les pièces. Cliquez en dehors de l’échiquier pour annuler la sélection.

Dans la fenêtre d’Exécution immédiate :

GuiDisplayBoardAt True, rowBoardMain, colBoardMain, boardMain

Basculer du VBE vers la feuille de calcul. L’échiquier a été affiché les Blancs en bas.

GuiDisplayBoardAt False, rowBoardMain, colBoardMain, boardMain

L’échiquier est maintenant affiché avec les Blancs en haut.


Libérons l’objet échiquier

Finalement en fin de session :

boardMain.FreeBoard

La mémoire de l’échiquier (collection de coups, de pièces, etc.) est libérée.

Set boardMain = Nothing

L’objet échiquier est libéré.


Code source VBA de Chess03.xls

NomTypeProceduresDLLLignesVolume
Board Class Module 39 0 346 11,9 K
Move Class Module 30 0 348 13,9 K
Piece Class Module 48 0 595 23,3 K
Player Class Module 52 0 925 39,1 K
Square Class Module 19 0 102 3,5 K
ModChess Standard Module 12 0 193 8,8 K
ModFen Standard Module 1 0 4 0,2 K
ModPgn Standard Module 0 0 27 1,0 K

L’objet Square est le plus petit et le plus simple des objets tandis que Player est 9 fois plus important.


Précédent : Paradoxe de la gallinacée et de l’œuf en VBA

Suivant : Chess VBA a de la classe

Posté le 21 juillet 2011 par Matt