Bonjour !
Je vous propose un "Puissance 4" basé sur les expressions régulières.
Puissance 4
Qu'en pensez-vous ?
Bonjour !
Je vous propose un "Puissance 4" basé sur les expressions régulières.
Puissance 4
Qu'en pensez-vous ?
J'ai trouvé un bug. Je vous propose de remplacer
par
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;
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;
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,
@+
@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 :
Merci de m'avoir signalé cette faiblesse.
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;
Voici les pions jaunes et rouges.
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.
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;
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 Button1Clickps: J'ai fait le teste sous D7 ... le problème vient peut être de là.
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;
Cordialement,
@+
@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.
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) :
Avoir des valeurs négatives n'est pas interdit.
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);
@Andnotor
Merci !
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;
Voilà, la nouvelle version est terminée.
Puissance 4
re,
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,
@+
@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 :
Mais pour le problème de lenteur, je n'ai pas d'idée.
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;
Fait.
Puissance 4
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 ?
J'ai relu le code de TetrisRun. Je vois deux différences avec le mien. D'abord ceci :
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 ?
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;
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.
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager