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 :

I-B. Les objectifs du défi

Le logiciel doit comporter les éléments suivants :

  1. Créer l'interface graphique du jeu
  2. 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.
  3. 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é :

 
Sélectionnez

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

Téléchargez le code source de Haywire
(anciennement Mushroom7)
Télécharger
Téléchargez l'exécutable de Haywire
(anciennement Mushroom7)
Télécharger

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.

  1. Interface
    • 10 - Mission accomplie ;
    • 5 - Ergonomie (rapport design/utilisabilité) ;
    • 5 - Design ;
    • 10 - Jouabilité / simplicité ;
    • 10 - Bogues et disfonctionnements.
  2. 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 Télécharger Télécharger
Eric Boisvert 17.88 2 Télécharger Télécharger
OutOfRange 17.25 3 Télécharger Télécharger
jejedelbarro 17 4 Télécharger Télécharger
anapurna 15.38 5 Télécharger Télécharger
Cpt Anderson 14.25 6 Télécharger Télécharger
Fabrice ROUXEL 1 13.13 7 Télécharger Télécharger
Paul TOTH hors concours   Télécharger Télécharger
Lady Wasky hors concours   Télécharger Télécharger
jobe hors concours   Télécharger Télécharger