Les consignes



Je tiens à ce qu'on se mette bien d'accord sur les règles du Pendu à réaliser. Je vais donc vous donner ici les consignes, c'est-à-dire vous expliquer comment doit fonctionner précisément le jeu que vous allez créer.

Tout le monde connaît le Pendu, n'est-ce pas ? Allez, un petit rappel ne peut pas faire de mal : le but du Pendu est de retrouver un mot caché en moins de 10 essais (mais vous pouvez changer ce nombre maximal pour corser la difficulté, bien sûr !).

Déroulement d'une partie


Supposons que le mot caché soit ROUGE.


Vous proposez une lettre à l'ordinateur, par exemple la lettre A. L'ordinateur vérifie si cette lettre se trouve dans le mot caché.

Rappelez-vous : il y a une fonction toute prête dans string.h pour rechercher une lettre dans un mot ! Notez que vous n'êtes cependant pas obligés de l'utiliser (personnellement, je ne m'en suis pas servi).


À partir de là, deux possibilités :

  • la lettre se trouve effectivement dans le mot : dans ce cas, on dévoile le mot avec les lettres qu'on a déjà trouvées ;
  • la lettre ne se trouve pas dans le mot (c'est le cas ici, car A n'est pas dans ROUGE) : on indique au joueur que la lettre ne s'y trouve pas et on diminue le nombre de coups restants. Quand il ne nous reste plus de coups (0 coup), le jeu est terminé et on a perdu.


Dans un « vrai » Pendu, il y aurait normalement le dessin d'un bonhomme qui se fait pendre au fur et à mesure que l'on fait des erreurs. En console, ce serait un peu trop difficile de dessiner un bonhomme qui se fait pendre rien qu'avec du texte, on va donc se contenter d'afficher une simple phrase comme « Il vous reste X coups avant une mort certaine ».


Supposons maintenant que le joueur tape la lettre G. Celle-ci se trouve dans le mot caché, donc on ne diminue pas le nombre de coups restants au joueur. On affiche le mot secret avec les lettres qu'on a déjà découvertes, c'est-à-dire quelque chose comme ça :

Mot secret : ***G*


Si ensuite on tape un R, comme la lettre s'y trouve, on l'ajoute à la liste des lettres trouvées et on affiche à nouveau le mot avec les lettres déjà découvertes :

Mot secret : R**G*


Le cas des lettres multiples


Dans certains mots, une même lettre peut apparaître deux ou trois fois, voire plus !


Par exemple, il y a deux Z dans PUZZLE ; de même, il y a trois E dans ELEMENT.

Que fait-on dans un cas comme ça ? Les règles du Pendu sont claires : si le joueur tape la lettre E, toutes les lettres E du mot ELEMENT doivent être découvertes d'un seul coup :

Mot secret : E*E*E**


Il ne faut donc pas avoir à taper trois fois la lettre E pour que tous les E soient découverts.


Exemple d'une partie complète


Voici à quoi devrait ressembler une partie complète en console lorsque votre programme sera terminé :

Bienvenue dans le Pendu !

 

Il vous reste 10 coups a jouer

Quel est le mot secret ? ******

Proposez une lettre : E


Il vous reste 9 coups a jouer

Quel est le mot secret ? ******

Proposez une lettre : A


Il vous reste 9 coups a jouer

Quel est le mot secret ? *A****

Proposez une lettre : O


Il vous reste 9 coups a jouer

Quel est le mot secret ? *A**O*

Proposez une lettre :


Et ainsi de suite jusqu'à ce que le joueur ait découvert toutes les lettres du mot (ou bien qu'il ne lui reste plus de coups à jouer) :

Il vous reste 8 coups a jouer

Quel est le mot secret ? MA**ON

Proposez une lettre : R


Gagne ! Le mot secret etait bien : MARRON


Saisie d'une lettre en console


La lecture d'une lettre dans la console est plus compliquée qu'il n'y paraît.
Intuitivement, pour récupérer un caractère, vous devriez avoir pensé à :

scanf("%c", &maLettre);


Et effectivement, c'est bien. %c indique que l'on attend un caractère, qu'on stockera dans maLettre (une variable de type char).

Tout se passe très bien… tant qu'on ne refait pas un scanf. En effet, vous pouvez tester le code suivant :

int main(int argc, char* argv[])

{

     char maLettre = 0;

      

     scanf("%c", &maLettre);

     printf("%c", maLettre);

    

     scanf("%c", &maLettre);

     printf("%c", maLettre);

    

     return 0;

}


Normalement, ce code est censé vous demander une lettre et vous l'afficher, et cela deux fois.


Testez. Que se passe-t-il ? Vous entrez une lettre, d'accord, mais… le programme s'arrête de suite après, il ne vous demande pas la seconde lettre ! On dirait qu'il ignore le second scanf.


Que s'est-il passé ?


En fait, quand vous entrez du texte en console, tout ce que vous tapez est stocké quelque part en mémoire, y compris l'appui sur la touche Entrée (\n). 

Ainsi, la première fois que vous entrez une lettre (par exemple A) puis que vous appuyez sur Entrée, c'est la lettre A qui est renvoyée par le scanf. Mais la seconde fois, scanf renvoie le \n correspondant à la touche Entrée que vous aviez pressée auparavant !

Pour éviter cela, le mieux c'est de créer notre propre petite fonction lireCaractere() :

char lireCaractere() 

    char caractere = 0;

 

    caractere = getchar(); // On lit le premier caractère

    caractere = toupper(caractere); // On met la lettre en majuscule si elle ne l'est pas déjà

 

    // On lit les autres caractères mémorisés un à un jusqu'au \n (pour les effacer) 

    while (getchar() != '\n') ;

 

    return caractere; // On retourne le premier caractère qu'on a lu 

}


Cette fonction utilise getchar() qui est une fonction de stdio qui revient exactement à écrire scanf("%c"&lettre);. La fonction getchar renvoie le caractère que le joueur a tapé.

Après, j'utilise une fonction standard qu'on n'a pas eu l'occasion d'étudier dans le cours : toupper(). Cette fonction transforme la lettre indiquée en majuscule. Comme ça, le jeu fonctionnera même si le joueur tape des lettres minuscules. Il faudra inclure ctype.h pour pouvoir utiliser cette fonction (ne l'oubliez pas !).

Vient ensuite la partie la plus intéressante : celle où je vide les autres caractères qui auraient pu avoir été tapés. En effet, en rappelant getchar on prend le caractère suivant que l'utilisateur a tapé (par exemple l'Entrée \n).
Ce que je fais est simple et tient en une ligne : j'appelle la fonction getchar en boucle jusqu'à tomber sur le caractère \n. La boucle s'arrête alors, ce qui signifie qu'on a « lu » tous les autres caractères, ils ont donc été vidés de la mémoire. On dit qu'on vide le buffer.


Pourquoi y a-t-il un point-virgule à la fin du while et pourquoi ne voit-on pas d'accolades ?


En fait, je fais une boucle qui ne contient pas d'instructions (la seule instruction, c'est le getchar entre les parenthèses). Les accolades ne sont pas nécessaires vu que je n'ai rien d'autre à faire qu'un getchar. Je mets donc un point-virgule pour remplacer les accolades. Ce point-virgule signifie « ne rien faire à chaque passage dans la boucle ». C'est un peu particulier je le reconnais, mais c'est une technique à connaître, technique qu'utilisent les programmeurs pour faire des boucles très courtes et très simples.

Dites-vous que le while aurait aussi pu être écrit comme ceci :

while (getchar() != '\n'

{


}



Il n'y a rien entre accolades, c'est volontaire, vu qu'on n'a rien d'autre à faire. Ma technique consistant à placer juste un point-virgule est simplement plus courte que celle des accolades.


Enfin, la fonction lireCaractere retourne le premier caractère qu'elle a lu : la variable caractere.

En résumé, pour récupérer une lettre dans votre code, vous n'utiliserez pas :

scanf("%c", &maLettre);



… vous utiliserez à la place notre super-fonction :

maLettre = lireCaractere();


Dictionnaire de mots


Dans un premier temps pour vos tests, je vais vous demander de fixer le mot secret directement dans votre code. Vous écrirez donc par exemple :

1

char motSecret[] = "MARRON";


Alors oui, bien sûr, le mot secret sera toujours le même si on laisse ça comme ça, ce qui n'est pas très rigolo. Je vous demande de faire comme ça dans un premier temps pour ne pas mélanger les problèmes. En effet, une fois que votre jeu de Pendu fonctionnera correctement (et seulement à partir de ce moment-là), vous attaquerez la seconde phase : la création du dictionnaire de mots.


Qu'est-ce que c'est, le « dictionnaire de mots » ?


C'est un fichier qui contiendra de nombreux mots pour votre jeu de Pendu. Il doit y avoir un mot par ligne. Exemple :

MAISON

BLEU

AVION

XYLOPHONE

ABEILLE

IMMEUBLE

GOURDIN

NEIGE

ZERO


À chaque nouvelle partie, votre programme devra ouvrir ce fichier et prendre un des mots au hasard dans la liste. Grâce à cette technique, vous aurez un fichier à part que vous pourrez éditer tant que vous voudrez pour ajouter des mots secrets possibles pour le Pendu.


Vous aurez remarqué que depuis le début je fais exprès d'écrire tous les mots du jeu en majuscules. En effet, dans le Pendu on ne fait pas la distinction entre les majuscules et les minuscules, le mieux est donc de se dire dès le début : « tous mes mots seront en majuscules ». À vous de prévenir le joueur, dans le mode d'emploi du jeu par exemple, qu'il est censé entrer des lettres majuscules et non des minuscules.
Par ailleurs, on fait exprès d'ignorer les accents pour simplifier le jeu (si on doit commencer à tester le é, le è, le ê, le ë… on n'a pas fini !). Vous devrez donc écrire vos mots dans le dictionnaire entièrement en majuscules et sans accents.


Le problème qui se posera rapidement à vous sera de savoir combien il y a de mots dans le dictionnaire. En effet, si vous voulez choisir un mot au hasard, il faudra tirer au sort un nombre entre 0 et X, et vous ne savez pas a priori combien de mots contient votre fichier.

Pour résoudre le problème, il y a deux solutions. Vous pouvez indiquer sur la première ligne du fichier le nombre de mots qu'il contient :

3

MAISON

BLEU

AVION


Cependant cette technique est ennuyeuse, car il faudra recompter manuellement le nombre de mots à chaque fois que vous en ajouterez un (ou ajouter 1 à ce nombre si vous êtes malins plutôt que de tout recompter, mais ça reste quand même une solution un peu bancale). Aussi je vous propose plutôt de compter automatiquement le nombre de mots en lisant une première fois le fichier avec votre programme. Pour savoir combien il y a de mots, c'est simple : vous comptez le nombre de \n (retours à la ligne) dans le fichier.

Une fois que vous aurez lu le fichier une première fois pour compter les \n, vous ferez un rewind pour revenir au début. Vous n'aurez alors plus qu'à tirer un nombre au sort parmi le nombre de mots que vous avez comptés, puis à vous rendre au mot que vous avez choisi et à le stocker dans une chaîne en mémoire.

Je vous laisse un peu réfléchir à tout cela, je ne vais pas trop vous aider quand même, sinon ça ne serait plus un TP ! Sachez que vous avez acquis toutes les connaissances qu'il faut dans les chapitres précédents, vous êtes donc parfaitement capables de réaliser ce jeu. Ça va prendre plus ou moins de temps et c'est moins facile qu'il n'y paraît, mais en vous organisant correctement (et en créant suffisamment de fonctions), vous y arriverez.

Bon courage, et surtout : per-sé-vé-rez !

Créé avec HelpNDoc Personal Edition: Créer des fichiers d'aide pour la plateforme Qt Help