Puissance 4 basé sur les expressions régulières

Présentation
Jouez à "Puissance 4" contre l'ordinateur.

Le jeu de l'adversaire artificiel est basé sur une évaluation instantanée de la position après le coup, au moyen d'expressions régulières.
Téléchargement
0  0 
Téléchargé 6 fois Voir les 28 commentaires
Détails
Catégories : Jeux
Avatar de Roland Chastain
Rédacteur / Modérateur
Voir tous les téléchargements de l'auteur
Licence : Non renseignée
Date de mise en ligne : 13 avril 2017




Avatar de Andnotor Andnotor - Rédacteur/Modérateur https://www.developpez.com
le 08/04/2017 à 12:05
J'ai jeté un œil et te propose quelques améliorations

L'utilisation d'un TImage n'est pas vraiment utile puisque tu as déjà une image de fond complète 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 systématiquement le rectangle. Initialise-le une fois et déplace-le par Offset.

Il y a un problème 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 saccadée.

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.

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure FormPaint(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    Dropping  :boolean;
    DropRect  :TRect;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  DropRect := TRect.Create(0,0,40,40);
  Dropping := TRUE;
end;

procedure TForm1.FormPaint(Sender: TObject);
begin
  Canvas.Brush.Color := clYellow;
  Canvas.Ellipse(DropRect);

  if Dropping then
  begin
    DropRect.Offset(0,1);
    Dropping := DropRect.Bottom < ClientHeight;
    Invalidate;
    Sleep(1);
  end;
end;
Avatar de Cirec Cirec - Membre éprouvé https://www.developpez.com
le 08/04/2017 à 13:08
re,

je viens d'essayer le code d'Andnotor et si comme pour moi rien ne se passe après l'appui sur Button1 il suffit
d'ajouter un "Invalidate" dans Button1Click
Code : Sélectionner tout
1
2
3
4
5
6
procedure TForm1.Button1Click(Sender: TObject);
begin
  DropRect := Rect(0,0,40,40);
  Dropping := TRUE;
  Invalidate;
end;
ps: J'ai fait le teste sous D7 ... le problème vient peut être de là.

Cordialement,
@+
Avatar de Andnotor Andnotor - Rédacteur/Modérateur https://www.developpez.com
le 08/04/2017 à 18:15
Citation Envoyé par Roland Chastain Voir le message
je ne trouve pas comment dessiner la grille vide quand la fenêtre s'ouvre. J'ai essayé de mettre des Invalidate un peu partout : ça ne donne rien : la grille n'apparaît que lorsque j'appuie sur le bouton.
Parce qu'il faut tout de même dessiner lorsqu'il n'y a pas de pion en mouvement (penser aussi au cas où la fiche repasse au premier plan) :
Code : Sélectionner tout
1
2
3
4
5
  if Dropping then
  begin
    ...
  end
  else Canvas.Draw(10, 10, FBuffer);
Citation Envoyé par Roland Chastain Voir le message
je voulais éviter qu'au premier passage le rectangle soit en dehors de l'image.
Avoir des valeurs négatives n'est pas interdit.
Avatar de Cirec Cirec - Membre éprouvé https://www.developpez.com
le 11/04/2017 à 12:46
re,
Citation Envoyé par Roland Chastain Voir le message
Voilà, la nouvelle version est terminée.
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 )
mais le plus embêtant c'est qu'à cause de l'animation on peut jouer un nouveau coup avant même que le précédent ne soit arrivé en bas
pire ... le joueur peut jouer plusieurs pions d'affilé


Cordialement,
@+
Avatar de Andnotor Andnotor - Rédacteur/Modérateur https://www.developpez.com
le 11/04/2017 à 13:45
Citation Envoyé par Roland Chastain Voir le message
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 démarrer 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.
Avatar de Andnotor Andnotor - Rédacteur/Modérateur https://www.developpez.com
le 12/04/2017 à 23:38
Citation Envoyé par Roland Chastain Voir le message
...qui (si je comprends bien) permet de sortir de la méthode OnPaint pour la rappeler aussitôt, tout en permettant à la machine de "respirer" entre temps ?
Ca permet de gérer la cadence d'affichage mais seul un sleep permet de faire "respirer la machine".
Ici on ne recalcule pas systématiquement l'image mais on ne s'arrête pas pour autant puisqu'une repeinture est immédiatement ordonnée.

Citation Envoyé par Roland Chastain Voir le message
L'autre différence, 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'arrête là.

Citation Envoyé par Roland Chastain Voir le message
J'ai ouvert le gestionnaire des tâches après avoir lancé TetrisRun : le programme occupe entre 40 et 50 % du processeur, ce qui est encore raisonnable, non ?
Ca dépend. Si l'app est au premier plan, on peut l'admettre aisément. Si elle est en arrière plan, définitivement pas.
Tu as manifestement un machine bi-coeurs, l'app est mono-thread (donc utilise un seul cœur) et cette tâche tourne à fond (en boucle sans sleep). 50% des ressources CPU sont utilisées, elle ne peut pas en consommer plus !

Le principe est très 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é légèrement supérieure aux autres, elle fonctionnera mais à la vitesse petit "V"

Citation Envoyé par Roland Chastain Voir le message
Maintenant rien ne me prouve que demain en lançant TetrisRun je ne vais pas observer le même phénomène de ralentissement. C'est ça qui est embêtant : que le phénomène se produise de façon irrégulière.
Le seul cas serait des tâches de priorité supérieure parce qu'ici, TetrisRun accapare un cœur pour son seul usage. Ce sont les autres apps qui risquent d'être ralenties mais pas lui
Avatar de Andnotor Andnotor - Rédacteur/Modérateur https://www.developpez.com
le 13/04/2017 à 16:52
Citation Envoyé par anapurna Voir le message
Ps : les exit dans le code m'horripile, même si il m'arrive de l'utiliser.
j'essai par dessus tout les moyens de ne pas l'utiliser ...
Quelle idée !

Exit est très utile et encore plus depuis qu'il est possible d'y passer en paramètre le résultat de la fonction. Le code est beaucoup plus lisible grâce à des niveaux d'imbrication beaucoup moins profonds.

Sans Exit :
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Cond1 := ...;

if Cond1 then
begin
  Cond2 := ...;

  if Cond2 then
  begin
    ...  
     Result := TRUE;
  end
  else Result := FALSE;
end
else Result := FALSE;
Avec Exit :
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
Cond1 := ...;
if not Cond1 then Exit(FALSE);

Cond2 := ...;
if not Cond2 then Exit(FALSE);

...
Result := TRUE;
Pour moi, y'a pas photo, j'aime les Exit
Avatar de Roland Chastain Roland Chastain - Rédacteur/Modérateur https://www.developpez.com
le 06/04/2017 à 21:46
Bonjour !

Je vous propose un "Puissance 4" basé sur les expressions régulières.



Puissance 4

Qu'en pensez-vous ?
Avatar de Roland Chastain Roland Chastain - Rédacteur/Modérateur https://www.developpez.com
le 07/04/2017 à 13:09
J'ai trouvé un bug. Je vous propose de remplacer

Code : Sélectionner tout
1
2
3
4
5
procedure TForm1.Button1Click(Sender: TObject);
begin
  if gEtatDuJeu <= gsBlackToMove then
    JouerCoup((Sender as TButton).Tag);
end;
par

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
procedure TForm1.Button1Click(Sender: TObject);
var
  x: integer;
begin
  if gEtatDuJeu <= gsBlackToMove then
  begin
    x := (Sender as TButton).Tag;
    if gGrille[x, 6] = NEANT then
      JouerCoup(x);
  end;
end;
Developpez.com décline toute responsabilité quant à l'utilisation des différents éléments téléchargés.