Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Algorithme pour jeu "Tetris"

9 réponses
Avatar
loufoque
Je pense que tout le monde connait le principe de ce jeu, aussi je ne
l'expliquerai pas.

Je recherche un bon algorithme pour pouvoir en même temps déplacer une
pièce vers la gauche ou la droite dès que l'utilisateur le souhaite et
que la pièce descende seule au bout d'un certain temps.

PS : J'utilise ncurses pour la partie graphique, mais le problème ne
vient pas de là.

J'ai donc fait ceci :

while(la piece peut descendre) {

touche = getchar(); /* non bloquant */

switch(touche) {

case KEY_LEFT:
on va à gauche;
break;

case KEY_RIGHT:
on va à droite;
break;

default:
sleep(1);
on va en bas;

}
}

Mais j'ai donc un décalage d'une seconde entre le moment où j'appuie sur
la touche pour aller à gauche et le moment où la pièce va à gauche,
puisque le programme est arrêté à ce moment à cause du sleep().
Ce qu'il faudrait, c'est que le sleep() s'arrête sur la pression d'une
touche gauche ou droite.

Je vois pas trop de moyen de faire ça proprement, alors si quelqu'un a
une idée...
Merci de me l'indiquer.

9 réponses

Avatar
Jean-Marc
"loufoque" a écrit:
...
J'ai donc fait ceci :

while(la piece peut descendre) {


save_clock=/* fonction mesure_du_temps qui passe (clock() ?) */


do
{
touche = getchar(); /* non bloquant */


if( touche==0
&& (mesure_du_temps - save_clock)>delai_que_lon_veut )
{
touche=KEY_DOWN;
}

}while( touche == 0 ); /* ??? */

switch(touche) {

case KEY_LEFT:
on va à gauche;
break;

case KEY_RIGHT:
on va à droite;
break;


case KEY_DOWN:
on va en bas;
break;


default:
sleep(1);
on va en bas;


Ne fonctionne pas, car si tu appuis une autre touche, le cas default
sera traité.

}
}



A
+
Jean-Marc
Novice N1

Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', loufoque wrote:

Je pense que tout le monde connait le principe de ce jeu, aussi je ne
l'expliquerai pas.

Je recherche un bon algorithme pour pouvoir en même temps déplacer une
pièce vers la gauche ou la droite dès que l'utilisateur le souhaite et
que la pièce descende seule au bout d'un certain temps.


Et quelle est la question sur le langage C?

PS : J'utilise ncurses pour la partie graphique, mais le problème ne
vient pas de là.

J'ai donc fait ceci :


Ok, admettons que c'est du pseudocode...

while(la piece peut descendre) {

touche = getchar(); /* non bloquant */

switch(touche) {

case KEY_LEFT:
on va à gauche;
break;

case KEY_RIGHT:
on va à droite;
break;

default:
sleep(1);
on va en bas;

}
}

Mais j'ai donc un décalage d'une seconde entre le moment où j'appuie sur
la touche pour aller à gauche et le moment où la pièce va à gauche,
puisque le programme est arrêté à ce moment à cause du sleep().
Ce qu'il faudrait, c'est que le sleep() s'arrête sur la pression d'une
touche gauche ou droite.

Je vois pas trop de moyen de faire ça proprement, alors si quelqu'un a
une idée...
Merci de me l'indiquer.


<Rien à voir avec le langage C...>
C'est un problème de conception. Il faut probablement dissocier la capture
d'informations en provenance du clavier et la génération d'un tic à une
seconde d'une part, et le traitement de ces évènements en série par le moteur
du jeu (calcul de la nouvelle position, mise à jour du tableau de données,
affichage) d'autre part.


Interruption clavier ---> /
Interruption timer ----->/ Synchronisation
----
| | File de message
----
|
v
. Tâche de traitements

Si ton système dispose déjà d'un mecanisme de gestion des évènements clavier
et timer par message, ainsi que de files et de threads, ça peut aider...
</>

A voir avec un forum dédié à ton système.

--
-ed- [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-reference: http://www.dinkumware.com/manuals/reader.aspx?lib=cpp
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/

Avatar
loufoque
Message d'origine de Emmanuel Delahaye :

Et quelle est la question sur le langage C?

Il est vrai que c'est plus une question algorithmique qu'un question sur

le C.
Le truc, c'est que je ne voyais pas comment mettre en place ce système
d'interruption en C, d'où ma demande.


Ok, admettons que c'est du pseudocode...
C'est du C simplifié, pour éviter de vous sortir des éléments plus

complexes inutiles au problème.


<Rien à voir avec le langage C...>
C'est un problème de conception. Il faut probablement dissocier la capture
d'informations en provenance du clavier et la génération d'un tic à une
seconde d'une part, et le traitement de ces évènements en série par le moteur
du jeu (calcul de la nouvelle position, mise à jour du tableau de données,
affichage) d'autre part.


Interruption clavier ---> /
Interruption timer ----->/ Synchronisation
----
| | File de message
----
|
v
. Tâche de traitements

Si ton système dispose déjà d'un mecanisme de gestion des évènements clavier
et timer par message, ainsi que de files et de threads, ça peut aider...
</>

A voir avec un forum dédié à ton système.



Je pensais qu'il existait peut-être une solution standard, avec la
bibliothèque signal par exemple, bien que je ne le connaisse pas du tout.

@Jean-Marc
Il est effectivement possible de faire une boucle qui vérifie le temps
donné par time() mais ce n'est pas très propre comme méthode. En plus ça
ne me permet pas de définir un temps inférieur à 1 seconde.

Avatar
Clément Goux
Salut

L'ideal ce serait d'utiliser des threads,
une pour la mise a jour interne avec signal a la librairie lors des maj
(on sort du wait lors de la reception d'un signal)
et l'autre pour l'affichage.

Ce serait quand meme plus élégant.
Mais ca dépend du niveau que tu a en prog. c.

Comme disais loufoque, tu peux tjs faire un compteur de temps, ca marche
mais c'est pas très élégant.

Clément

Message d'origine de Emmanuel Delahaye :


Et quelle est la question sur le langage C?



Il est vrai que c'est plus une question algorithmique qu'un question sur
le C.
Le truc, c'est que je ne voyais pas comment mettre en place ce système
d'interruption en C, d'où ma demande.


Ok, admettons que c'est du pseudocode...


C'est du C simplifié, pour éviter de vous sortir des éléments plus
complexes inutiles au problème.


<Rien à voir avec le langage C...>
C'est un problème de conception. Il faut probablement dissocier la
capture d'informations en provenance du clavier et la génération d'un
tic à une seconde d'une part, et le traitement de ces évènements en
série par le moteur du jeu (calcul de la nouvelle position, mise à
jour du tableau de données, affichage) d'autre part.


Interruption clavier ---> /
Interruption timer ----->/ Synchronisation
----
| | File de message
----
|
v . Tâche de traitements

Si ton système dispose déjà d'un mecanisme de gestion des évènements
clavier et timer par message, ainsi que de files et de threads, ça
peut aider...
</>

A voir avec un forum dédié à ton système.



Je pensais qu'il existait peut-être une solution standard, avec la
bibliothèque signal par exemple, bien que je ne le connaisse pas du tout.

@Jean-Marc
Il est effectivement possible de faire une boucle qui vérifie le temps
donné par time() mais ce n'est pas très propre comme méthode. En plus ça
ne me permet pas de définir un temps inférieur à 1 seconde.



Avatar
DINH Viêt Hoà

L'ideal ce serait d'utiliser des threads,


où est la question sur le langage C comme le dirait je ne sais
plus qui ...

tiens, je me souviens de tetris qui ont été fait sans thread, ni
signaux, on doit pouvoir s'en sortir de façon plus simple ...

--
DINH V. Hoa,

etPan! - newsreader, mail user agent -- http://libetpan.sf.net/etpan

Avatar
Jean-Michel Bechet
tiens, je me souviens de tetris qui ont été fait sans thread, ni
signaux, on doit pouvoir s'en sortir de façon plus simple ...



Ben oui, une 'petite' machine d'états suffira amplement.
Y'avait pas d'OS multitâche pour le Z80 de notre bon vieux gameboy ...

Avatar
loufoque
Message d'origine de Clément Goux :
L'ideal ce serait d'utiliser des threads,


Donc de l'api pthread (POSIX) ?

une pour la mise a jour interne avec signal a la librairie lors des maj
(on sort du wait lors de la reception d'un signal)


Y'a pas de wait() dans pthread. C'est *_join()
Le wait() c'est quand on fait des fork() je crois (qui créé alors un
nouveau processus enfant)

Enfin bref,
Je me demande bien comment on pouvait faire ça sur gameboy sans
multi-processus et sans multi-threading.
Si quelqu'un est capable de m'expliquer...

Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', loufoque wrote:

Je me demande bien comment on pouvait faire ça sur gameboy sans
multi-processus et sans multi-threading.
Si quelqu'un est capable de m'expliquer...


Qui te dit qu'il n'y avait pas de threads? Quand je faisais du 8051, j'avais
un système multitâche (maison). 100% en assembleur (vive les macro
assembleurs Intel!)

Sinon, la bonne vielle boucle de fond permet de faire des tas de choses
'ensembles'. Il suffit que personne ne soit blocant. Exemple bien connu en
Turbo C:

#include <conio.h>
#include <time.h>
#include <stddef.h>

int main (void)
{
int end = 0;
time_t next_sec = time (NULL);

clrscr ();

while (!end)
{
/* non-blocking keyboard */
if (kbhit ())
{
int c = getch ();
switch (c)
{
case 27: /* ESC */
end = 1;
break;

default:
/* echo */
putch (c);;
}
}

/* clock in the corner */
{
time_t now = time (NULL);

if (now == next_sec)
{
int x = wherex ();
int y = wherey ();
struct tm t = *gmtime (&now);;

next_sec = now + 1;

gotoxy (73, 1);
cprintf ("%02u:%02u:%02u"
,(unsigned) t.tm_hour
,(unsigned) t.tm_min
,(unsigned) t.tm_sec);

gotoxy (x, y);
}
}
}
return 0;
}

--
-ed- [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-reference: http://www.dinkumware.com/manuals/reader.aspx?lib=cpp
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/

Avatar
DINH Viêt Hoà

Sous Linux, je ne sais pas comment on fait.


Comme sous windows à priori.

--
DINH V. Hoa,

etPan! - newsreader, mail user agent -- http://libetpan.sf.net/etpan