# Environnements de dveloppement > Delphi > Codes sources  tlcharger >  Puissance 4 bas sur les expressions rgulires [Sources]

## Roland Chastain

Bonjour !

Je vous propose un "Puissance 4" bas sur les expressions rgulires.



 ::arrow::  Puissance 4

Qu'en pensez-vous ?

----------


## Roland Chastain

J'ai trouv un _bug_. Je vous propose de remplacer



```

```

par



```

```

----------


## Cirec

Bonjour Roland,

je viens juste de tlcharger l'archive (Merci pour le partage) et j'ai jou avec de suite (sans correction)
et dois dire que j'aime beaucoup ... a me rappelle des souvenirs  ::D: 

Cot code c'est un peu trop tt pour donner un avis (je n'ai pas encore regard)

J'ai tout de mme trouv moyen de gagner  tous les coups  ::mrgreen:: 

Avec les blancs tu joues la squence suivante :
D E A G F
ou encore celle-ci :
D C G B A

Ce qui ne pas empch de me faire battre par l'algo. en jouant d'autres coups  ::mouarf:: 

Sinon, si je devais ajouter quelque chose, je dirais que je m'attendais  voir des pions Rouges et Jaunes  :;): 
c'est tellement ancr dans l'esprit ... 

Cordialement,
@+

----------


## Roland Chastain

@Cirec

Bonjour ! Merci pour le retour.

Je prends bonne note des deux squences gagnantes que tu as trouves. Je vais voir si je trouve un correctif.

Pour la couleur des pions, j'ajouterai une option dans la prochaine version.  ::): 

P.-S. Je pense que la modification suivante (dans le fichier _puissance4.adversaire.pas_) devrait faire l'affaire :



```

```

Merci de m'avoir signal cette faiblesse.  ::ccool::

----------


## Roland Chastain

Voici les pions jaunes et rouges.  :;):

----------


## Roland Chastain

J'ai retravaill sur l'affichage : je voulais voir tomber les pions. Je suis assez content du rsultat. Je vous le montre pour avoir votre avis et vos suggestions ventuelles.

J'ai deux bitmaps et une image. L'image est pour l'ensemble de la grille. Les bitmaps sont pour une colonne. Il y a un bitmap qui est dessin une seule fois au lancement de l'application et qui reprsente le fond de la colonne. Le deuxime bitmap est celui sur lequel le pion est dessin. Je me suis servi de la mthode CopyRect() pour ne copier  chaque fois que ce qui est ncessaire.

----------


## Andnotor

J'ai jet un il et te propose quelques amliorations  :;): 

L'utilisation d'un _TImage_ n'est pas vraiment utile puisque tu as dj une image de fond complte et un buffer de travail. Peindre cela sur le canvas de la fiche serait suffisant et plus souple (tu verras ci-dessous).

Tu n'a pas besoin de recalculer systmatiquement le rectangle. Initialise-le une fois et dplace-le par Offset.

Il y a un problme de fluidit pour deux raisons :
1. un pas de 20 est trop important ;
2. tu cumules les messages non prioritaires (_WM_TIMER_, _WM_PAINT_), l'animation est saccade.

Le _timer_ n'a pas de raison d'tre si tu te passes du _TImage_, il te suffit d'ordonner une nouvelle repeinture (_Invalidate_)  la fin de... la repeinture (_OnPaint_) et cela jusqu' ce que le pion soit en position.



```

```

----------


## Cirec

re,

je viens d'essayer le code d'Andnotor et si comme pour moi rien ne se passe aprs l'appui sur Button1 il suffit
d'ajouter un "Invalidate" dans Button1Click

```

```

ps: J'ai fait le teste sous D7 ... le problme vient peut tre de l.

Cordialement,
@+

----------


## Roland Chastain

@Andnotor

Merci beaucoup pour ta rponse trs intructive. Effectivement le rsultat est bien meilleur en suivant ta mthode. Voici l'tat actuel de mon projet. C'est idiot, mais je ne trouve pas comment dessiner la grille vide quand la fentre s'ouvre. J'ai essay de mettre des Invalidate un peu partout : a ne donne rien : la grille n'apparat que lorsque j'appuie sur le bouton.

P.-S. Bien not l'astuce du dplacement du rectangle par la mthode Offset, mais comme je dfinis un rectangle qui commence plus haut que la position actuelle du pion (pour effacer l'image du pion  l'instant prcdent), je voulais viter qu'au premier passage le rectangle soit en dehors de l'image.

----------


## Andnotor

> je ne trouve pas comment dessiner la grille vide quand la fentre s'ouvre. J'ai essay de mettre des Invalidate un peu partout : a ne donne rien : la grille n'apparat que lorsque j'appuie sur le bouton.


Parce qu'il faut tout de mme dessiner lorsqu'il n'y a pas de pion en mouvement (penser aussi au cas o la fiche repasse au premier plan) :


```

```




> je voulais viter qu'au premier passage le rectangle soit en dehors de l'image.


Avoir des valeurs ngatives n'est pas interdit.

----------


## Roland Chastain

@Andnotor

Merci !  ::ccool::

----------


## Roland Chastain

J'ai presque fini de reconstruire le jeu.

En mettant un Sleep(100);  la fin de la mthode _onPaint_, je m'aperois qu'elle est appele pour le dessin de chaque bouton : plus exactement, il y a d'abord un rectangle blanc qui apparat, correspondant  la surface occupe par l'ensemble des boutons, puis les boutons sont dessins un par un. Est-ce qu'il n'y aurait pas un moyen de faire en sorte que tous les boutons, qui sont crs dans la mthode _FormCreate_, soient dessins en une seule fois ?



```

```

----------


## Roland Chastain

Voil, la nouvelle version est termine.

 ::arrow::  Puissance 4

----------


## Cirec

re,



> Voil, la nouvelle version est termine.


je viens de tester et je pense que l'animation pourrait tre un peu plus rapide (on dirait que l'on joue avec une gravit Lunaire  ::P:  )
mais le plus embtant c'est qu' cause de l'animation on peut jouer un nouveau coup avant mme que le prcdent ne soit arriv en bas 
pire ... le joueur peut jouer plusieurs pions d'affil 


Cordialement,
@+

----------


## Roland Chastain

@Cirec

Merci pour l'essai. Oui, moi aussi j'ai constat ce problme de lenteur. Ce qui est trange, c'est que par moment le programme fonctionne correctement (les pions tombent rapidement).  ::weird:: 

Je n'avais pas remarqu qu'on pouvait jouer plusieurs coups  la fois. a devrait pouvoir se rgler en ajoutant ceci :



```

```

Mais pour le problme de lenteur, je n'ai pas d'ide.  ::roll::

----------


## Andnotor

> Ce qui est trange, c'est que par moment le programme fonctionne correctement (les pions tombent rapidement).


_Sleep_ redonne la main  l'OS qui va dmarrer le _thread_ suivant en fonction de sa planification.
Donc plus l'OS est "charg", plus le pion tombera lentement.

Il faudrait augmenter la priorit pour voir.

----------


## Roland Chastain

> Il faudrait augmenter la priorit pour voir.


Merci pour ta rponse. J'ai essay de changer la priorit dans le gestionnaire des tches : apparemment a ne rsout pas le problme.  ::roll:: 

 moins que vous n'ayez une autre ide, je crois que je n'ai plus qu' ajouter une option pour dsactiver l'animation "chute des pions".  ::pleure::

----------


## Roland Chastain

> moins que vous n'ayez une autre ide, je crois que je n'ai plus qu' ajouter une option pour dsactiver l'animation "chute des pions".


Fait.

 ::arrow::  Puissance 4

----------


## Roland Chastain

Voici deux jeux de pions supplmentaires, fabriqus avec BGRABitmap (code original).

Que faut-il retenir, selon vous, de cette discussion ? La mthode propose par Andnotor donne un excellent rsultat mais que faire de ce problme de ralentissement alatoire ?

Je suis en train de regarder le code du TetrisRun de Paul TOTH. Ce programme utilise le mme principe d'une "repeinture" continuelle mais semble-t-il avec une approche lgrement diffrente (un chronomtre). Est-ce que ce serait la solution ?

----------


## Roland Chastain

J'ai relu le code de TetrisRun. Je vois deux diffrences avec le mien. D'abord ceci :



```

```

qui (si je comprends bien) permet de sortir de la mthode OnPaint pour la rappeler aussitt, tout en permettant  la machine de "respirer" entre temps ?  ::roll:: 

L'autre diffrence, c'est qu'il n'y a pas de Sleep(). Peut-tre justement le code ci-dessus en tient-il lieu ?

J'ai ouvert le gestionnaire des tches aprs avoir lanc TetrisRun : le programme occupe entre 40 et 50 % du processeur, ce qui est encore raisonnable, non ?

Maintenant rien ne me prouve que demain en lanant TetrisRun je ne vais pas observer le mme phnomne de ralentissement. C'est a qui est embtant : que le phnomne se produise de faon irrgulire.  ::roll::

----------


## Andnotor

> ...qui (si je comprends bien) permet de sortir de la mthode OnPaint pour la rappeler aussitt, tout en permettant  la machine de "respirer" entre temps ?


Ca permet de grer la cadence d'affichage mais seul un _sleep_ permet de faire "respirer la machine".
Ici on ne recalcule pas systmatiquement l'image mais on ne s'arrte pas pour autant puisqu'une repeinture est immdiatement ordonne.




> L'autre diffrence, c'est qu'il n'y a pas de Sleep(). Peut-tre justement le code ci-dessus en tient-il lieu ?


Les deux provoquent un ralentissement du mouvement mais la comparaison s'arrte l.




> J'ai ouvert le gestionnaire des tches aprs avoir lanc TetrisRun : le programme occupe entre 40 et 50 % du processeur, ce qui est encore raisonnable, non ?


Ca dpend. Si l'app est au premier plan, on peut l'admettre aisment. Si elle est en arrire plan, dfinitivement pas.
Tu as manifestement un machine bi-coeurs, l'app est _mono-thread_ (donc utilise un seul cur) et cette tche tourne  fond (en boucle sans _sleep_). 50% des ressources CPU sont utilises, elle ne peut pas en consommer plus !

Le principe est trs bien et assure un mouvement plus uniforme. Il manque peut-tre juste un test if GetForgroundWindow <> Handle then Sleep(1); pour que si tout  coup tu devais utiliser une autre app (lire tes mails par exemple) sans pour autant quitter le jeu, cette autre app ne subisse pas de ralentissement.

(L'app au premier plan a une priorit lgrement suprieure aux autres, elle fonctionnera mais  la vitesse petit "V")




> Maintenant rien ne me prouve que demain en lanant TetrisRun je ne vais pas observer le mme phnomne de ralentissement. C'est a qui est embtant : que le phnomne se produise de faon irrgulire.


Le seul cas serait des tches de priorit suprieure parce qu'ici, _TetrisRun_ accapare un cur pour son seul usage. Ce sont les autres apps qui risquent d'tre ralenties mais pas lui  :;):

----------


## Roland Chastain

@Andnotor

Merci pour ces explications. Je commence  y voir plus clair.

J'ai vrifi : oui, il y a bien deux curs sur ma machine.

J'ai essay d'ajouter dans TetrisRun la ligne que tu proposais :



```

```

a fonctionne trs bien : c'est--dire que si TetrisRun est au premier plan, a ne change rien, mais s'il passe au second plan, par exemple lorsque j'ouvre le gestionnaire des tches, on voit que l'animation devient moins fluide, et l'occupation du processeur n'est plus que de 30 % environ.

----------


## anapurna

> ...
> 
> 
> ```
> 
> ```


arf j'aime pas ce genre de code  ::D:  
si tu veut que la personne n'appuie pas sur le bouton lors du fonctionnement
tu conditionne la disponibilit du bouton vis a vis de ta variable 


```
Button.enabled := not(FDropping);
```

ainsi tu rend ton bouton invalide le temps du traitement.

Ps : les exit dans le code m'horripile, mme si il m'arrive de l'utiliser. 
j'essai par dessus tout les moyens de ne pas l'utiliser ... c'est comme le goto c'est a proscrire le plus possible  :;):

----------


## Roland Chastain

Voici une nouvelle version, avec une option "Highest animation speed".



```

```

 ::arrow::  Puissance 4

@anapurna
Merci pour ta suggestion. Je vais y penser pour la prochaine mise  jour.  :;):

----------


## Andnotor

> Ps : les exit dans le code m'horripile, mme si il m'arrive de l'utiliser. 
> j'essai par dessus tout les moyens de ne pas l'utiliser ...


Quelle ide !

_Exit_ est trs utile et encore plus depuis qu'il est possible d'y passer en paramtre le rsultat de la fonction. Le code est beaucoup plus lisible grce  des niveaux d'imbrication beaucoup moins profonds.

Sans _Exit_ :


```

```

Avec _Exit_ :


```

```

Pour moi, y'a pas photo, j'aime les _Exit_  :;):

----------


## anapurna

salut 

je suis un vieux de la vielle qui aime bien pouvoir reproduire 
les programme sous forme d'algorithme 
ma reprsentation prfr tant sous la forme de 
diagramme NassiShneiderman 

de plus je suis persuad que plus nous restons prs des rgles lmentaire de l'algorithmie 
plus il est simple de passer d'un langage  l'autre  et plus il est simple de maintenir et de modifier le source

----------


## Cirec

re,

tout d'abords merci pour les nouvelles images en couleurs  :;): 

ensuite, j'avoue ne pas comprendre le choix d'utiliser le Sleep pour grer une animation ...
je veux dire que Sleep est une mthode bloquante elle met en pause (endort) le thread principale !

d'ailleurs on voit bien bien  quelle point l'animation est ralentie juste avec un Sleep(1) 
1 milliseconde thoriquement mais rien que l'appel prend plus de temps do un ralentissement plus important que prvu.
et si tu avais une autre animation ou processus qui s'excuterait en mme temps sur le thread principale il subirait le mme ralentissement !

Sinon as-tu retouch l'expression rgulire qui contrle le jeux depuis que tu as corrig le fait qu'on pouvait gagner  tous les coups avec 2 squence ?

Parce que depuis que tu as ajout l'animation cette squence :
D D C F E C
permet  nouveau de gagner  tous les coups (mais pas les 2 premires que j'avais trouvs) !!!!
alors qu'avec la dernire version juste avant l'ajout de l'animation a ne marche pas !

je trouve a assez bizarre parce que je ne pense pas que tu aies touch  a pour ajouter l'animation ... !
mais bon le fait est l.

je viens de faire le teste et c'est bien l'animation (l'utilisation du Sleep certainement) qui permet de gagner avec cette squence  ::aie:: 
quand on Disable l'animation la squence ne passe pas  ::aie:: 

Cordialement,
@+

----------


## Roland Chastain

@Cirec

Merci pour l'essai et le compte-rendu.

C'est assez inquitant ce que tu me dis l (que le fait de dsactiver l'animation change le jeu de l'ordinateur). Cela mrite une vrification en profondeur. Je fais a dans les jours qui viennent et vous tiens au courant.

Je te confirme que je n'ai pas retouch le code qui produit les coups de l'adversaire artificiel.

----------


## Roland Chastain

@Cirec

Chez moi, quelles que soient les options d'animation, la squence que tu as indique est toujours gagnante.  ::roll:: 

Autrement, pour en revenir au problme du Sleep, c'est vrai que par moments l'animation est d'une lenteur insupportable, mais  d'autres moments elle est d'une rapidit trs satisfaisante. Cela dpend, j'imagine, de l'occupation de la machine. En revanche, avec le Sleep, le programme sollicite moins le processeur.

En l'occurrence, comme l'animation ne dure qu'une seconde (le temps que le pion tombe), on peut sans trop d'inconvnient je crois se passer du Sleep. Voil ce que j'ai retenu de cette discussion.  :;): 

Pour l'adversaire artificiel, c'est normal qu'il ait de grosses faiblesses, vu que l'valuation se base sur la position suivant immdiatement le coup. Quand j'aurai le temps, je retravaillerai cette partie du programme.

----------

