| 
  • If you are citizen of an European Union member nation, you may not use this service unless you are at least 16 years old.

  • You already know Dokkio is an AI-powered assistant to organize & manage your digital files & messages. Very soon, Dokkio will support Outlook as well as One Drive. Check it out today!

View
 

jeu z80 le pendu

Page history last edited by adriweb 16 years, 1 month ago

Qui n'a jamais fait un pendu avec son voisin un jour où il/elle s'ennuyait en cours (quoique les filles c'est plus du bavardage XD)

Aujourd'hui, nous allons apprendre à faire une version assez simplifiée du pendu pas à pas, et bien expliqué :)

Pour rendre le "cours" plus intéressant, nous allons supposer que je parle à un utilisateur lambda qui posera les questions que vous vous posez en lisant ce tuto

Citation:

Lambda : bonjour

Bonjour. Nous allons pouvoir commencer le jeu du pendu


Tout d'abord, mettre en oeuvre le programme : un programme se code d'abord dans la tête ou sur le papier avant de se coder sur machine :)

Nous allons donc imaginer comment se déroulera le jeu

Ce sera un jeu à 2 joueurs, le 2ème joueur essaiera de deviner le mot que le 1er joueur a entré...

Voyons comment cela va se passer :

Tout d'abord, le joueur 2 entre le mot à deviner par le joueur 1, ce mot sera stocké dans une chaine, Str1 par exemple

V (comme vie) sera le nombre de vies restantes au joueur 1

R (comme restant) sera le nombre de lettres restantes à trouver

Fin du jeu : V=0 (perdu) ou R=0 (gagné)

Ici, la procédure est plutôt simple, pour d'autres jeux, cela peut être beaucoup plus compliqué...

Mettons donc en oeuvre tout ça


1.Le 2ème joueur rentre le mot à deviner, on vérifie ensuite la validité de la chaine entrée

Code:

0->V
While V=0 //tant que la chaine n'est pas valide
0->V  //V permettra de savoir si la chaine entrée est valide
ClrHome //efface l'écran
Input "MOT?",Str0 //demande...le mot ^^

//code de vérification de validité
If length(Str0)<23 //1er test: on teste que la taille est valide
Then //oui, la taille est valide
"ABCDEFGHIJKLMNOPQRSTUVWXYZ ->Str9 //caractères valides
1->V
For(Z,1,length(Str0     //on parcourt la chaine
If not(inString(Str9,sub(Str0,Z,1 //cf explications après le code
0->V //chaine non valide
End  //fin de la boucle
Else  //taille non valide
0->V //chaine non valide
End //fin de la 1ère condition (taille)
End //fin de la boucle while

Citation:

Lambda : hmm, un peu compliqué tout ça...

Effectivement, mais tout va s'éclaircir avec mes explications Very Happy

Prenons les 4 cas qui peuvent se présenter et regardons la valeur de V ligne par ligne

  • Taille valide et caractères valides
Code:

If length(Str0)<23 //V=0
Then //V=0
"ABCDEFGHIJKLMNOPQRSTUVWXYZ ->Str9 //V=0
1->V //V=1
For(Z,1,length(Str0     //V=1
If not(inString(Str9,sub(Str0,Z,1 //V=1
0->V //Tous les caractères sont valides, V ne change pas : V=1
End  //V=1
Else  //taille valide, ça ne nous concerne pas
0->V
End
End //fin de la boucle while, finalement V=1

  • Taille valide et caractère(s) invalide(s)
Code:

If length(Str0)<23 //V=0
Then //V=0
"ABCDEFGHIJKLMNOPQRSTUVWXYZ ->Str9 //V=0
1->V //V=1
For(Z,1,length(Str0     //V=1
If not(inString(Str9,sub(Str0,Z,1 //V=1
0->V //Un caractère invalide (ou plus) a été trouvé : V=0
End  //V=1
Else  //taille valide, ça ne nous concerne pas
0->V
End
End //fin de la boucle while, finalement V=0

  • Taille invalide et caractères valides
  • Taille invalide et caractère(s) invalide(s)
J'ai regroupé ces 2 cas, car le comportement sera le même, puisque étant donné que la taille est invalide, le programme ne testera pas la validité des caractères : elle "sautera" la boucle For() et passera directement au "Else"

Code:

If length(Str0)<23 //non : V=0
Then
"ABCDEFGHIJKLMNOPQRSTUVWXYZ ->Str9
1->V
For(Z,1,length(Str0
If not(inString(Str9,sub(Str0,Z,1
0->V
End
Else  //taille invalide
0->V //V=0
End
End //fin de la boucle while, finalement V=0

Finalement c'est bien ce que l'on veut : le programme continuera uniquement si la taille et les caractères sont valides

Citation:

Lambda : hmm...ok, mais ce serait possible d'expliquer un peu plus le code ?

Oui, j'y viens, je ferais juste une remarque avant : Seules les lettres sont considérées comme des lettres valides ainsi que le caractère espace : si vous voulez inclure par exemple les chiffres, modifiez Str9 et ajoutez-y "0123456789" à la fin

Maintenant, revenons au code : la ligne qui doit sûrement poser problème doit être la ligne

Code:

If not(inString(Str9,sub(Str0,Z,1

On va décomposer cette ligne pour la comprendre :

Tout d'abord, sub(Str0,Z,1) : cela permet d'extraire le Zème caractère de la chaine entrée (rappel : Z est la variable qui nous sert à parcourir la chaine du début à la fin)

L'instruction inString(Str9,sub(Str0,Z,1 recherche le caractère extrait dans la chaine Str9 : "ABCDEFGHIJKLMNOPQRSTUVWXYZ ". Pour rappel, la fonction inString(chaine,sous-chaine) trouve la 1ère occurence de sous-chaine dans chaine, ou 0 si sous-chaine n'a pas été trouvée

(voir tuto sur les chaines de caractères)

Si le caractère extrait n'a pas été trouvé dans Str9, cela retourne donc 0

Le If not(inString(Str9,sub(Str0,Z,1 permet de vérifier si la fonction inString() a retourné 0 ou non

le not( utilisé ici est une optimisation, not(expression) est une fonction qui retourne 1 si expression est non nul, 0 sinon

Ainsi, si le caractère extrait n'a pas été trouvé, inString(Str9,sub(Str0,Z,1 sera égal à 0, donc en prenant le "not()" de tout ça, on obtient 1

Vous remarquerez qu'il n'y a pas de signe "=" dans la condition : en effet, en cas d'absence du signe, la condition devient

If ... (différent de) 0

le "(différent de) 0" étant implicite

Citation:

Lambda : ok, donc je peux écrire
Code:

If 0!=inString(Str9,sub(Str0,Z,1  //!= : différent de

?

Exactement. L'optimisation que l'on a faite a permis de gagner 2 octets

Citation:

Lambda : c'est rien 2 octets...

Oui, mais c'est toujours 2 octets de gagnés, dans les énormes programmes, un "expert" pourrait gagner 500 octets avec des petits trucs comme ça (ou plus avancés, mais là n'est pas la question)

Une fois la validité de la chaine testée, on passe à la suite...

2.Initialisation des variables de jeu

Ici, rien de compliqué, il s'agit simplement de stocker des valeurs dans des variables...

Code:

6->V   //nombre de vies restantes
length(Str0)-2->R   //nombre de lettres restantes
For(Z,2,length(Str0)-1   //parcours de la boucle
If " "=sub(Str0,Z,1 //s'il s'agit d'un espace
R-1->R   //on enlève 1 du nombre de lettres restantes
End
0->K   //touche pressée
" ->Str2  //lettres déjà proposées

Remarque pour R : -2 pour les lettres de début et de fin et ensuite on enlève tous les espaces

3.Le jeu

Nous y voilà, le coeur du programme :)

Tout d'abord, afficher le tout

Code:

ClrDraw    //efface l'écran de dessin
Text(0,0,sub(Str0,1,1  //premier caractère
For Z,2,length(Str0)-1   //boucle
Text(0,4Z-4,"-             //affiche un tiret à la place de la lettre
End
Text(0,4*length(Str0)-4,sub(Str0,length(Str0),1    //dernier caractère

Y a t-il besoin d'explications ici ? On affiche simplement la 1ère lettre, puis on affiche l'un après l'autre les caractères à deviner en les remplaçant par des tirets, et enfin le dernier caractère

Pour faire simple et rapide :

1
2
3
4
5
...
length(Str0)-1
length(Str0)
A A A A A ... A A
A - - - - ... - A

Nous allons ensuite faire une boucle tant que il reste des vies et des lettres restantes

tant que ? oui, une boucle while !

Code:

While V>0 and R>0 //tant qu'il reste des vies et des lettres
...
End

On affiche quelques informations pratiques (code à l'intérieur de la boucle !)

Code:

Text(8,0,"Vies restantes=",V
Text(14,0,"Lettres restantes=",R
Text(22,0,"Lettres proposées    //A l'extérieur de la boucle
Text(28,0,Str2                        //Str2 regroupe les lettres proposées

On attend ensuite qu'une touche soit pressée (évidemment, ce code est à l'intérieur de la boucle...)

Code:

0->K
Repeat K
GetKey->K
End

Note pour le Repeat K : il s'agit encore d'une optimisation, on peut également écrire While K=0 (encore 2 octets)

Rappel : Repeat est "l'inverse" du While : les 2 codes sont équivalents :

Code:

Repeat K=0    //tant que K n'est pas égal à 0
While K!=0     //tant que K est différent de 0

Repeat est plus avantageux lorsqu'il y a plusieurs conditions pour terminer une boucle : en effet, while s'arrête si une seule condition n'est plus verifiée, alors que repeat continue jusqu'à ce que les 2 conditions ne soient plus vérifiées

Citation:

Lambda : pratique, ça ^^

Une fois qu'on a le code touche, on l'associe au caractère correspondant : attention, ligne de code barbare !

Code:

(K>=51)(K<=93)(5int(.1K)-22+K-10int(.1K))+(K>=41)(K<=43)(K-10int(.1K
If Ans
sub(Str9,Ans,1->Str1

Citation:

Lambda : o_O ^ 10000

Il s'agit simplement d'une succession de If condensés

Cette ligne peut se ré-écrire de la façon suivante :

Code:

If K>=51 and K<=93
5int(.1K)-22+K-10int(.1K
If K>=41 and K<=43
K-10int(.1K

Je ne vais pas développer cette ligne, il s'agit d'un code retournant le caractère associé à une touche, cela évite les

Code:

If K=41
"A->Str1
If K=42
"B->Str1
...
If K=93
"Z"->Str1

Et permet ainsi un gain de temps, de place et de vitesse considérable

Simplement, le Ans est une variable système qui contient la réponse de la dernière instruction/du dernier calcul.

Une fois le caractère du joueur 1 obtenu, il s'agit de vérifier s'il se trouve dans la chaine proposée par le joueur 2 au départ ; pour cela, il faut se référer au tuto sur les chaines de caractères, car inString() ne suffira pas s'il y a plusieurs fois la même lettre dans le mot :

Code:

If not(inString(Str2,Str1     //Si on n'a pas encore proposé la lettre
Then
0->T                              //Lettre n'apparait pas
For(Z,2,length(Str0)-1       //parcourt la chaine
If Str1=sub(Str0,Z,1
Then
R-1->R                           //1 lettre de moins !
1->T                             //Eh si, elle y apparait !
Text(0,4*Z-4,Str1           //On remplace le tiret par la lettre
End
End
If T=0                            //La lettre n'apparait pas...
V-1->V                          //1 vie de moins !
Str2+Str1->Str2               //On marque la lettre comme proposée !
End

Même principe que pour vérifier la validité, mais beaucoup plus simple :

on part du principe que la lettre proposée n'est pas dans la chaine, alors T=0

On parcourt ensuite la chaine pour voir si elle y est : si oui, on change la valeur de T en 1, sinon T reste en 0 à la fin de la boucle, et on perd une vie

Juste après ce code, vient le End qui clot la boucle While


Et c'est ainsi que se termine le pendu, résumons le code complet :

Code:

0->V
While V=0 //tant que la chaine n'est pas valide
0->V  //V permettra de savoir si la chaine entrée est valide
ClrHome //efface l'écran
Input "MOT?",Str0 //demande...le mot ^^

//code de vérification de validité
If length(Str0)<23 //1er test: on teste que la taille est valide
Then //oui, la taille est valide
"ABCDEFGHIJKLMNOPQRSTUVWXYZ ->Str9 //caractères valides
1->V
For(Z,1,length(Str0     //on parcourt la chaine
If not(inString(Str9,sub(Str0,Z,1 //cf explications après le code
0->V //chaine non valide
End  //fin de la boucle
Else  //taille non valide
0->V //chaine non valide
End //fin de la 1ère condition (taille)
End //fin de la boucle while
6->V   //nombre de vies restantes
length(Str0)-2->R   //nombre de lettres restantes
For(Z,2,length(Str0)-1   //parcours de la boucle
If " "=sub(Str0,Z,1 //s'il s'agit d'un espace
R-1->R   //on enlève 1 du nombre de lettres restantes
End
0->K   //touche pressée
" ->Str2  //lettres déjà proposées
ClrDraw    //efface l'écran de dessin
Text(0,0,sub(Str0,1,1  //premier caractère
For Z,2,length(Str0)-1   //boucle
Text(0,4Z-4,"-             //affiche un tiret à la place de la lettre
End
Text(0,4*length(Str0)-4,sub(Str0,length(Str0),1    //dernier caractère
Text(22,0,"Lettres proposées    //A l'extérieur de la boucle
While V>0 and R>0 //tant qu'il reste des vies et des lettres
Text(8,0,"Vies restantes=",V
Text(14,0,"Lettres restantes=",R

Text(28,0,Str2                        //Str2 regroupe les lettres proposées
0->K
Repeat K
GetKey->K
End
(K>=51)(K<=93)(5int(.1K)-22+K-10int(.1K))+(K>=41)(K<=43)(K-10int(.1K
If Ans
Then
sub(Str9,Ans,1->Str1
If not(inString(Str2,Str1     //Si on n'a pas encore proposé la lettre
Then
0->T                              //Lettre n'apparait pas
For(Z,2,length(Str0)-1       //parcourt la chaine
If Str1=sub(Str0,Z,1
Then
R-1->R                           //1 lettre de moins !
1->T                             //Eh si, elle y apparait !
Text(0,4*Z-4,Str1           //On remplace le tiret par la lettre
End
End
If T=0                            //La lettre n'apparait pas...
V-1->V                          //1 vie de moins !
Str2+Str1->Str2               //On marque la lettre comme proposée !
End
End
End  //fin de la boucle While

Et voilà un joli pendu pour les cours ^^

Vous pouvez ensuite l'améliorer en ajoutant des graphiques, en permettant plus de caractères, en ajoutant des bonus ou en interdisant de proposer des voyelles, à vous de voir ^^

En tout cas, cela devrait bien aider pour les programmeurs débutants (j'l'espère en tout cas), s'il y a encore des points incompris ou autres choses, faites-moi signe :)

adri>oui, tu peux l'utiliser pour le wiki Very Happy


Pour conclure, le programme complet en cas d'erreur lors de la copie et la capture d'écran qui va avec

 

Comments (0)

You don't have permission to comment on this page.