IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Langage C - Jeu - Créer un chronomètre en continu sans thread


Sujet :

C

  1. #1
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2015
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2015
    Messages : 7
    Points : 2
    Points
    2
    Par défaut Langage C - Jeu - Créer un chronomètre en continu sans thread
    Bonjour Développeurs, Développeuses,

    Je fais appel à vous aujourd'hui car malgré avoir fait plusieurs recherches, lu beaucoup de tuto et de forums, je n'arrive toujours pas coder ce qu'il me faut.

    Dans le cadre d'un jeu en langage C en console, je dois créer et afficher un chronomètre en continu, sachant que je déplace un personnage (un caractère) dans une matrice, à chaque pression des numéros 2, 4, 6, ou 8 sur le pavé numérique, et sachant que je ne peux pas utiliser de thread.

    D'après ce que j'ai lu, il faut que je me serve de la librairie <time.h> mais je sais pas si je dois par la suite me servir de time_t ou clock_t.

    Autre problème, j'utilise getch() pour la récupération du caractère saisi sur le pavé numérique ce qui est bloquant.

    Merci d'avance

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 369
    Points : 23 623
    Points
    23 623
    Par défaut
    Bonjour et bienvenue,

    Cela relève de la programmation système et dépend donc de la famille d'OS que tu utilises. Sous un système compatible POSIX, tu peux soit t'appuyer sur select() en passant une valeur de timeout, soit utiliser alarm() pour recevoir un signal à l'échéance. Dans les deux cas, ceci aura pour effet de débloquer ta lecture de touche même si aucune frappe n'a été effectuée. Il faut donc vérifier ce cas et embarquer le tout dans une boucle sans fin qui permet de revenir au début après chaque événement, pour attendre le suivant.

  3. #3
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2015
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2015
    Messages : 7
    Points : 2
    Points
    2
    Par défaut
    Tout d'abord merci de ta réponse.

    D'après ce que j'ai compris, ce que tu me proposes c'est de faire un décompte où j'envoi à alarm() ou select() le temps de ce décompte, or ce que je désire c'est l'inverse, c'est une horloge démarrant à 0 au lancement du jeu et qui s'incrémente.
    Je sais qu'il y a un moyen de le faire à partir de clock() ou time() seulement je ne vois pas comment.

  4. #4
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 369
    Points : 23 623
    Points
    23 623
    Par défaut
    Bonsoir,

    Pas tout-à-fait : je te suggère de définir un intervalle correspondant à la période de ton chronomètre, par exemple « une seconde ». Ça veut dire que quoi qu'il se passe, l'appel mettra ton processus en attente soit jusqu'à l'appui sur une touche, soit jusqu'à l'échéance du délai d'une seconde, soit la réception d'un autre signal (cas qu'il faudra éventuellement gérer).

    Juste après l'appel (et donc quand celui-ci a rendu la main), tu vérifies s'il y a des caractères en attente et, le cas échéant, tu les gères comme tu l'entends, puis tu vérifies si la valeur de timeout a été atteinte (dans le cas de select()) et si c'est le cas, tu incrémentes la position de ton chronomètre.

  5. #5
    Membre averti
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Juin 2012
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2012
    Messages : 257
    Points : 321
    Points
    321
    Par défaut
    Bonjour,

    Au début du programme tu prends un "time_t depart=time(NULL);"

    Puis en boucle des "temps=time(NULL);" tu mets à jour ton chrono avec difftime(depart, temps)

  6. #6
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 369
    Points : 23 623
    Points
    23 623
    Par défaut
    Citation Envoyé par nanosoft Voir le message
    Bonjour,

    Au début du programme tu prends un "time_t depart=time(NULL);"
    Puis en boucle des "temps=time(NULL);" tu mets à jour ton chrono avec difftime(depart, temps)
    Fort bien, mais comment peut-il le faire si sa boucle est bloquée par l'attente de l'appui sur une touche ?

  7. #7
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2015
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2015
    Messages : 7
    Points : 2
    Points
    2
    Par défaut
    Je pense avoir compris le concept Obsidian, seulement je ne vois pas trop comment mettre cela en place.. Je n'ai jamais utilisé alarm() et select().

    Merci pour la réponse nanosoft, j'avais vu cela même comme l'a indiqué Obsidian cette solution est bloquante

  8. #8
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 369
    Points : 23 623
    Points
    23 623
    Par défaut
    Citation Envoyé par FireBear Voir le message
    Je pense avoir compris le concept Obsidian, seulement je ne vois pas trop comment mettre cela en place.. Je n'ai jamais utilisé alarm() et select().
    Il suffit de lire les man pages :
    http://man.developpez.com/man2/select/
    http://man.developpez.com/man2/alarm/

    Par contre, le signal SIGALRM déclenché par alarm() à l'échéance tue le programme s'il n'est pas intercepté et SIG_IGN l'ignore sans débloquer les appels. Donc il faudra écrire un tout petit handler (vide) uniquement pour l'intercepter.

    Sinon, tu te rabats sur select(). Ça vaut le coup de l'apprendre parce que cela te permet ensuite de surveiller plusieurs entrées à la fois et, in fine, de gérer proprement les sockets.

  9. #9
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2015
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2015
    Messages : 7
    Points : 2
    Points
    2
    Par défaut
    Si j'ai bien compris, à la fin du temps que j'aurais envoyé en paramètre à alarm() ou select(), cela va mettre fin au getch() et après il faudra traiter le cas où un caractère a été tapé et celui où rien a été tapé ?
    Et donc en couplant cela à un compteur que j'affiche, j'aurais mon chronomètre ?

    EDIT : J'ai essayé de faire le programme de test suivant, mais j'ai une erreur de compilation qui m'indique que ALRM n'est pas déclaré, comment cela se fait-il ?
    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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <signal.h>
    #include <sys/unistd.h>
     
    void timeout(int signum)
    {
        exit(0);
    }
     
     
    int main()
    {
        char c;
        signal(SIGALRM, timeout);
     
        alarm(1);
     
        c = getch();
     
        return 0;
    }

  10. #10
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 369
    Points : 23 623
    Points
    23 623
    Par défaut
    Bonjour,

    Ton programme de test compile (pratiquement) chez moi. Il faut simplement utiliser getchar() et pas getch(), qui elle est une fonction DOS/Windows OU une fonction de ncurses. Il faut également retirer le exit(0) de ton handler (et donc le laisser vide) puisqu'on installe ce handler justement pour éviter de tuer le programme.

    Après, c'est SIGALRM et non ALRM seul qui est défini, mais à aucun moment tu n'utilises ce dernier dans ton programme, donc il n'y a pas de raison pour que cette erreur se produise…

  11. #11
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2015
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2015
    Messages : 7
    Points : 2
    Points
    2
    Par défaut
    Bonjour,

    Je me suis trompé, l'erreur de compilation concerne bien SIGALRM et cela même après avoir supprimé exit(0), et remplacé getch() par getchar().

    Je n'ai pas trouvé comment résoudre ce problème ...

  12. #12
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 369
    Points : 23 623
    Points
    23 623
    Par défaut
    Peux-tu copier-coller ici ton programme exact ainsi que le message d'erreur associé ?
    Sous quel système d'exploitation compiles-tu ton programme ?

  13. #13
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2015
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2015
    Messages : 7
    Points : 2
    Points
    2
    Par défaut
    Voici un screenshot de Code::Blocks
    Nom : Sans titre 3.png
Affichages : 3442
Taille : 38,1 Ko

    Je suis sous Windows 10

  14. #14
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 369
    Points : 23 623
    Points
    23 623
    Par défaut
    Citation Envoyé par FireBear Voir le message
    Je suis sous Windows 10
    Ça peut être le problème puisque SIGALRM est un signal défini au niveau du système (et par POSIX), et non par la norme C elle-même contrairement aux signaux les plus connus.

    Essaie d'ajouter la macro suivante tout en haut de ton programme, AVANT même les #includes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define _POSIX_C_SOURCE 200112L
    Sinon, essaie de n'inclure que <unistd.h> ou <sys/unistd.h>, alternativement.

  15. #15
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2015
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2015
    Messages : 7
    Points : 2
    Points
    2
    Par défaut
    Après avoir ajouté la ligne de code fourni et essayé alternativement <unistd.h> et <sys/unistd.h>, j'ai toujours la même erreur...

  16. #16
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 369
    Points : 23 623
    Points
    23 623
    Par défaut
    Après quelques recherches, il semblerait que MinGW traîne quelques casseroles concernant cet appel.

    Essaie d'ajouter #define HAVE_DECL_ALARM 1 tout en haut de ton programme également, et d'inclure #include <io.h> si ça ne marche toujours pas. Sinon, on essaiera avec select().

Discussions similaires

  1. Réponses: 19
    Dernier message: 14/09/2007, 03h01
  2. Quel langage choisir pour créer un programme de gestion d'entreprise ?
    Par amerex dans le forum Langages de programmation
    Réponses: 4
    Dernier message: 10/09/2007, 20h09
  3. Créer un chronomètre
    Par lebossejames dans le forum Assembleur
    Réponses: 3
    Dernier message: 25/03/2007, 14h18
  4. Réponses: 13
    Dernier message: 06/11/2005, 21h37

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