I. Le sujet de ce quatrième défi▲
Le sujet de ce quatrième n'a pas été proposé par un membre de l'équipe Delphi, mais bien par un membre du site.
Haywire nous propose la création du jeu : jouez au Serpent !
Il s'agit de réaliser le jeu selon les règles énoncées par l'auteur.
Merci à Haywire de nous avoir proposé ce défi !
I-A. Prérequis▲
Pour réaliser ce défi, une simple édition personnelle de Delphi suffit.
Pas besoin d'avoir les bibliothèques spécifiques aux versions Pro/Entreprise/Architecte !
Certaines versions personnelles de DELPHI sont disponibles au téléchargement sur Developpez.com.
Il peut être nécessaire de savoir farfouiller dans la rubrique DELPHI et plus particulièrement dans :
- la F.A.Q. DELPHI ;
- les Sources DELPHI ;
- les tutoriels DELPHI ;
- les forums DELPHI.
I-B. Les objectifs du défi▲
Le logiciel doit comporter les éléments suivants :
- Créer l'interface graphique du jeu
- Respecter les règles suivantes du jeu du Serpent :
- Le joueur contrôle un serpent qui se déplace dans l'aire de jeu et qui apparait à un endroit prédéfini en début de partie.
- Une grenouille apparaît aléatoirement sur l'aire de jeu.
- Lorsque le serpent mange une grenouille, il s'allonge et une nouvelle grenouille apparaît au hasard sur l'aire de jeu.
- Si le serpent sort de l'aire de jeu ou touche son propre corps, il meurt.
- Laissez libre cours à votre imagination et proposez vos propres fonctionnalités !
Les participant doivent respecter les règles du défi, et le déroulement du défi et plus précisément que "l'utilisation de composantes ou bibliothèques autres que celles fournies en standard par Embarcadero sont interdites, qu'elles soient commerciales, freewares, open-source etc."
II. La solution du défieur▲
Haywire, selon les règles du défi, a réussi à mettre au point un tel logiciel avant que le défi ne soit lancé sur le forum.
II-A. Structure du programme▲
Le programme est consitué de quatre unités, deux frames et une fiche principale.
Dans ma version j'ai proposé deux modes de jeu.
Un mode « classique » illimité, où l'on joue « jusqu'à la mort » et un mode multi-niveaux, où l'on passe au niveau suivant lorsque l'on atteint un certain score.
Dans ce mode, le joueur dispose de plusieurs vies.
Il y a également plusieurs niveaux de difficulté, qui influencent la vitesse de déplacement du serpent et le nombre de vies.
II-A-1. Unité "USerpent"▲
Elle représente la structure logique du serpent.
N'étant pas encore à l'aise avec les classes Pascal, j'ai utilisé l'unité elle-même comme une sorte de classe.
La structure utilisée est semblable à une file, implémentée sous la forme d'une liste simplement chaînée.
Les éléments de la file sont les anneaux du serpent.
Un anneau est représenté par un record qui contient les données x et y ainsi qu'un pointeur vers l'anneau suivant.
X et Y représentent les coordonnées de cet anneau.
Pour accès, on dispose d'un pointeur sur la tête du serpent, ainsi que d'un pointeur sur sa queue (qui sont tous deux des anneaux).
Le type TSerpent est donc un record qui contient un pointeur sur la tête et un pointeur sur la queue mais aussi la direction du serpent.
La direction est de type TDirection, qui correspond à l'ensemble (NORD, EST, SUD, OUEST).
L'unité USerpent définit quatre procédures et deux fonctions.
Les fonctions getQueue et getTete renvoient un résultat de type TCoord.
Le type TCoord est défini comme un tableau de TPoint éléments de type integer.
Le type TPoint définit un couple (x,y).
Voici les déclarations de types de cette unité :
type
TDirection = (NORD, EST, SUD, OUEST);
TPointeurAnneau = ^TAnneau;
TAnneau = record
x, y: Integer
;
svt: TPointeurAnneau;
end
;
TSerpent = record
tete, queue: TPointeurAnneau;
direction: TDirection;
end
;
TPoint = (x, y);
TCoord = array
[ TPoint ] of
Integer
;
II-A-2. Unité "UMatrice"▲
Elle représente la structure de la zone de jeu.
La structure utilisée est une matrice classique sous forme de tableau de tableaux.
Les éléments de la matrice sont de type TColor et représentent la couleur de la case.
II-A-3. Unité "UPrincipale"▲
C'est l'unité associée à la fiche principale.
C'est également l'unité qui contrôle le déroulement du jeu.
Elle définit plusieurs constantes :
- CASEVIDE : la couleur d'une case vide de la matrice ;
- CORPS : la couleur du corps du serpent ;
- TETE : la couleur de la tête du serpent ;
- GRENOUILLE : la couleur des grenouilles ;
- OBSTACLE : la couleur des obstacles.
et plusieurs variables :
Nom variable | Informations | Type |
---|---|---|
S | le serpent | TCoord |
oldTete | les coordonnées de la tête avant un déplacement | TCoord |
newTete | les coordonnées de la tête après un déplacement | TCoord |
oldQueue | les coordonnées de la queue avant un déplacement | TCoord |
Score | le score | Cardinal |
ScoreMax | le score à atteindre dans le mode multi-niveaux | Cardinal |
Niveau | le niveau de jeu | Cardinal |
Vie | le nombre de vies restantes | Cardinal |
L'affichage est réalisé à l'aide d'un DrawGrid.
II-B. Déroulement d'un déplacement▲
Le joueur contrôle le serpent grâce aux touches fléchées.
Le serpent se déplace également automatiquement toutes les X millisecondes dans sa direction actuelle, grâce à un Timer.
Que ce soit le joueur ou le timer qui déplace le serpent, l'événement correspondant appelle la procédure déplacement en lui indiquant la direction dans laquelle déplacer le serpent. La procédure reçoit également la variable serpent en paramètre ; ceci permet de gérer plusieurs serpents au cas ou l'on ajouterait un mode à deux joueurs.
La procédure déplacement appelle les fonctions getTete et getQueue pour obtenir la position actuelle de la tête et de la queue du serpent et place les coordonnées dans les variables correspondantes, à savoir oldTete et oldQueue.
Ensuite elle appelle la procédure deplacerSerpent en lui donnant la direction adéquate et appelle la fonction getTete pour obtenir la nouvelle position de la tête, qui sera stockée dans la variable newTete.
En dernier lieu, la procédure vérifie que le serpent s'est réellement déplacé en comparant les coordonnées de la tête avant et après le déplacement (oldTete et newTete).
Ceci est nécessaire car si le joueur appuie sur la touche fléchée opposée à la direction du serpent, celui-ci ne doit pas se déplacer.
Si le serpent s'est déplacé, elle passe le contrôle à la procédure "statutPartie".
Celle-ci vérifie si le joueur a perdu ou non.
Pour cela elle vérifie que le serpent n'est pas sorti de l'aire du jeu, qu'il ne s'est pas mordu lui-même et qu'il n'a pas touché un obstacle ; grâce à la variable newTete et aux contantes CORPS et OBSTACLE.
Selon le résultat, elle passe le contrôle à la procédure perdu ou à la procédure continue.
La procédure "perdu" se contente de remettre l'interface graphique dans un état correct et d'afficher un message au joueur.
La procédure "continue" doit vérifier si le serpent a mangé une grenouille ou non.
Pour cela, elle compare la couleur de la case correspondant à la position de la nouvelle tête du serpent à la constante GRENOUILLE.
S'il y a bien une grenouille dans cette case, elle remplace sa couleur par la couleur de la tête du serpent, et la case correspondant à l'ancienne position de la tête du serpent prend la couleur du corps du serpent.
Les variables sont également mises à jour (score, etc).
S'il n'y a pas de grenouille dans cette case, elle appelle la procédure couperQueue, qui « coupe » la queue du serpent, et la matrice est mise à jour de la même façon qu'expliqué ci-dessus, à ceci près que l'ancienne position de la queue prend la couleur d'une case vide.
Rappelez-vous que lorsque le serpent se déplace, il s'allonge, et c'est seulement ensuite que la queue est coupée ou non.
II-C. Conclusion▲
Voilà pour l'essentiel, pour plus détails reportez-vous au code source complet du programme.
II-D. Téléchargement▲
III. Les résultat du défi: Jouez au serpent !▲
III-A. Conclusion▲
Tout d'abord, l'équipe tient à féliciter tous les participants, Haywire pour avoir proposé ce défi et Cl@udius pour nous avoir aidé à noter.
En outre, merci de votre patience pour les résultats de ce défi.
Un grand BRAVO à
Andry
pour son programme qui a réussi à allier simplicité et jouabilité du jeu, avec un code source clair et cohérent.
L'équipe du Défi Delphi offre au vainqueur un chèque cadeau.
III-B. Grille de notation▲
L'équipe s'est efforcée de noter avec un maximum d'objectivité les programmes soumis au défi, tant pour l'interface utilisateur que pour le programme en lui-même.
Cette grille a été établie et utilisée par l'équipe pour noter chaque participant.
Chaque rubrique est précédée du nombre de points sur laquelle elle a été notée.
-
Interface
- 10 - Mission accomplie ;
- 5 - Ergonomie (rapport design/utilisabilité) ;
- 5 - Design ;
- 10 - Jouabilité / simplicité ;
- 10 - Bogues et disfonctionnements.
-
Programme
- 10 - Clarté générale/élégance du code ;
- 10 - Optimisations/code optimal ;
- 10 - Indépendance des fonctions ;
- 10 - Warnings/Conseils/Bogues.
Total des rubriques = 80 points.
Chaque noteur a ramené les notes de cette grille sur 20 points (très scolaire tout ça ;-) )
Les notes présentées dans la section suivante sont les moyennes de tous les noteurs confondus.
III-C. Classement des participants et téléchargements▲
Classement des participants et moyennes des notes sur 20.
Les notes sont établies selon le fonctionnement décrit en section précédente.
Parcipant | Moyenne | Classement | Sources | Executable |
---|---|---|---|---|
Andry | 19.38 | 1 | ||
Eric Boisvert | 17.88 | 2 | ||
OutOfRange | 17.25 | 3 | ||
jejedelbarro | 17 | 4 | ||
anapurna | 15.38 | 5 | ||
Cpt Anderson | 14.25 | 6 | ||
Fabrice ROUXEL 1 | 13.13 | 7 | ||
Paul TOTH | hors concours | |||
Lady Wasky | hors concours | |||
jobe | hors concours |