1. #1
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    2 993
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 2 993
    Points : 10 780
    Points
    10 780
    Billets dans le blog
    4

    Par défaut Puissance 4 basé sur les expressions régulières

    Bonjour !

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

    Nom : puissance4-delphi.png
Affichages : 123
Taille : 11,8 Ko

    Puissance 4

    Qu'en pensez-vous ?

  2. #2
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    2 993
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 2 993
    Points : 10 780
    Points
    10 780
    Billets dans le blog
    4

    Par défaut

    J'ai trouvé un bug. Je vous propose de remplacer

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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 - Visualiser dans une fenêtre à part
    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;

  3. #3
    Membre averti Avatar de Cirec
    Profil pro
    Inscrit en
    octobre 2010
    Messages
    203
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : octobre 2010
    Messages : 203
    Points : 426
    Points
    426

    Par défaut

    Bonjour Roland,

    je viens juste de télécharger 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

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

    J'ai tout de même trouvé moyen de gagner à tous les coups

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

    Ce qui ne pas empêché de me faire battre par l'algo. en jouant d'autres coups

    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,
    @+

  4. #4
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    2 993
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 2 993
    Points : 10 780
    Points
    10 780
    Billets dans le blog
    4

    Par défaut

    @Cirec

    Bonjour ! Merci pour le retour.

    Je prends bonne note des deux séquences gagnantes que tu as trouvées. 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 :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    function Evaluer2(const aGrille: TGrillePuissance4; const aJoueur: boolean): integer;
    begin
      result := Evaluer1(aGrille, aJoueur) - {2}3 * Evaluer1(aGrille, not aJoueur); // <----
    end;
    Merci de m'avoir signalé cette faiblesse.

  5. #5
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    2 993
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 2 993
    Points : 10 780
    Points
    10 780
    Billets dans le blog
    4

    Par défaut

    Voici les pions jaunes et rouges.
    Fichiers attachés Fichiers attachés

  6. #6
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    2 993
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 2 993
    Points : 10 780
    Points
    10 780
    Billets dans le blog
    4

    Par défaut

    J'ai retravaillé sur l'affichage : je voulais voir tomber les pions. Je suis assez content du résultat. 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 représente le fond de la colonne. Le deuxième bitmap est celui sur lequel le pion est dessiné. Je me suis servi de la méthode CopyRect() pour ne copier à chaque fois que ce qui est nécessaire.
    Fichiers attachés Fichiers attachés

  7. #7
    Rédacteur/Modérateur
    Avatar de Andnotor
    Profil pro
    Inscrit en
    septembre 2008
    Messages
    4 405
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : septembre 2008
    Messages : 4 405
    Points : 8 963
    Points
    8 963

    Par défaut

    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 - Visualiser dans une fenêtre à part
    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;

  8. #8
    Membre averti Avatar de Cirec
    Profil pro
    Inscrit en
    octobre 2010
    Messages
    203
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : octobre 2010
    Messages : 203
    Points : 426
    Points
    426

    Par défaut

    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 - Visualiser dans une fenêtre à part
    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,
    @+

  9. #9
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    2 993
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 2 993
    Points : 10 780
    Points
    10 780
    Billets dans le blog
    4

    Par défaut

    @Andnotor

    Merci beaucoup pour ta réponse très intructive. Effectivement le résultat est bien meilleur en suivant ta méthode. Voici l'état actuel de mon projet. C'est idiot, mais 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.

    P.-S. Bien noté l'astuce du déplacement du rectangle par la méthode Offset, mais comme je définis un rectangle qui commence plus haut que la position actuelle du pion (pour effacer l'image du pion à l'instant précédent), je voulais éviter qu'au premier passage le rectangle soit en dehors de l'image.
    Fichiers attachés Fichiers attachés

  10. #10
    Rédacteur/Modérateur
    Avatar de Andnotor
    Profil pro
    Inscrit en
    septembre 2008
    Messages
    4 405
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : septembre 2008
    Messages : 4 405
    Points : 8 963
    Points
    8 963

    Par défaut

    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 - Visualiser dans une fenêtre à part
    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.

  11. #11
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    2 993
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 2 993
    Points : 10 780
    Points
    10 780
    Billets dans le blog
    4

    Par défaut

    @Andnotor

    Merci !

  12. #12
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    2 993
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 2 993
    Points : 10 780
    Points
    10 780
    Billets dans le blog
    4

    Par défaut

    J'ai presque fini de reconstruire le jeu.

    En mettant un Sleep(100); à la fin de la méthode onPaint, je m'aperçois qu'elle est appelée pour le dessin de chaque bouton : plus exactement, il y a d'abord un rectangle blanc qui apparaît, correspondant à la surface occupée par l'ensemble des boutons, puis les boutons sont dessinés un par un. Est-ce qu'il n'y aurait pas un moyen de faire en sorte que tous les boutons, qui sont créés dans la méthode FormCreate, soient dessinés en une seule fois ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
      for x := 1 to 7 do
      begin
        FButtons[x] := TButton.Create(Self);
        with FButtons[x] do
        begin
          Parent := Self;
          Name := Chr(x + Ord('A') - 1);
          Left := 40 * Pred(x) + MARGE;
          Top := ActionMainMenuBar1.Height + 280 + 2 * MARGE;
          Width := 40;
          Height := 25;
          Tag := x;
          onClick := ButtonClick;
        end;

  13. #13
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    2 993
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 2 993
    Points : 10 780
    Points
    10 780
    Billets dans le blog
    4

    Par défaut

    Voilà, la nouvelle version est terminée.

    Puissance 4

  14. #14
    Membre averti Avatar de Cirec
    Profil pro
    Inscrit en
    octobre 2010
    Messages
    203
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : octobre 2010
    Messages : 203
    Points : 426
    Points
    426

    Par défaut

    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é
    Nom : 1 Shot.png
Affichages : 62
Taille : 39,8 Ko

    Cordialement,
    @+

  15. #15
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    2 993
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 2 993
    Points : 10 780
    Points
    10 780
    Billets dans le blog
    4

    Par défaut

    @Cirec

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

    Je n'avais pas remarqué qu'on pouvait jouer plusieurs coups à la fois. Ça devrait pouvoir se régler en ajoutant ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    procedure TForm1.ButtonClick(Sender: TObject);
    ...
    begin
      if FDropping then
        Exit;
    Mais pour le problème de lenteur, je n'ai pas d'idée.

  16. #16
    Rédacteur/Modérateur
    Avatar de Andnotor
    Profil pro
    Inscrit en
    septembre 2008
    Messages
    4 405
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : septembre 2008
    Messages : 4 405
    Points : 8 963
    Points
    8 963

    Par défaut

    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.

  17. #17
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    2 993
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 2 993
    Points : 10 780
    Points
    10 780
    Billets dans le blog
    4

    Par défaut

    Citation Envoyé par Andnotor Voir le message
    Il faudrait augmenter la priorité pour voir.
    Merci pour ta réponse. J'ai essayé de changer la priorité dans le gestionnaire des tâches : apparemment ça ne résout pas le problème.

    À moins que vous n'ayez une autre idée, je crois que je n'ai plus qu'à ajouter une option pour désactiver l'animation "chute des pions".

  18. #18
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    2 993
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 2 993
    Points : 10 780
    Points
    10 780
    Billets dans le blog
    4

    Par défaut

    Citation Envoyé par Roland Chastain Voir le message
    À moins que vous n'ayez une autre idée, je crois que je n'ai plus qu'à ajouter une option pour désactiver l'animation "chute des pions".
    Fait.

    Puissance 4

  19. #19
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    2 993
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 2 993
    Points : 10 780
    Points
    10 780
    Billets dans le blog
    4

    Par défaut

    Voici deux jeux de pions supplémentaires, fabriqués avec BGRABitmap (code original).

    Que faut-il retenir, selon vous, de cette discussion ? La méthode proposée par Andnotor donne un excellent résultat mais que faire de ce problème de ralentissement aléatoire ?

    Je suis en train de regarder le code du TetrisRun de Paul TOTH. Ce programme utilise le même principe d'une "repeinture" continuelle mais semble-t-il avec une approche légèrement différente (un chronomètre). Est-ce que ce serait la solution ?
    Fichiers attachés Fichiers attachés

  20. #20
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    2 993
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 2 993
    Points : 10 780
    Points
    10 780
    Billets dans le blog
    4

    Par défaut

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

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    procedure TMainForm.FormPaint(Sender: TObject);
    ...
    begin
      QueryPerformanceCounter(Time);
      // Faire défiler la route en fonction du temps passé depuis le dernier rendu
      delta := Round(FSpeed * ((Time - FCount)/FFreq));
      if delta = 0 then
      begin
        InvalidateRect(Handle, nil, False);
        Exit;
      end;
    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 ?

    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 ?

    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 ?

    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.

Discussions similaires

  1. Réponses: 3
    Dernier message: 22/05/2008, 22h22
  2. question sur les expressions régulières
    Par goanes dans le forum Langage
    Réponses: 2
    Dernier message: 02/09/2007, 23h34
  3. Question sur les expressions régulières
    Par zarbiman dans le forum java.util
    Réponses: 5
    Dernier message: 03/04/2007, 14h27
  4. Question sur les expressions régulières
    Par espadon1 dans le forum Langage
    Réponses: 2
    Dernier message: 05/07/2006, 08h59

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo