M1103 – TP2 – Exercice 1

Mettre de la couleur dans le terminal sous GNU / Linux

Puisque les cours d’IHM (Interface Homme Machine) ne commencent qu’au second semestre, nous allons voir comment nous pouvons spécifier, dans un programme, la couleur des caractères ainsi que celle du fond d’une console, mais aussi effacer son contenu.
Puisque la console est une émulation d’un terminal VT100, toutes les instructions que nous allons lui donner commencent par \033[. Ensuite, une autre séquence d’instruction, concaténée à la première, provoque l’effacement de l’écran, le changement de la couleur de la police ou du fond.

Remarque : les informations évoquées dans cette partie fonctionnent aussi sous Mac OS-X, mais pas sous Windows.

Effacer l’écran

Afin d’effacer l’écran, la seconde séquence est : H\033[2J. En conséquence, la fonction suivante permet d’effacer l’écran :

void ClearScreen ()
{
    cout << "\033[H\033[2J";
}

Copiez la, et mettez la dans votre espace de nom anonyme.

Changer la couleur

Afin de changer la couleur, la seconde séquence est : XXm, où m est le code de la couleur souhaitée. Ce code est constitué de 2 chiffres comme le montre le tableau suivant :

Couleur Code associé
0 réinitialise le système de couleur à la valeur par défaut du shell
30 Noir
31 Rouge
32 Vert
33 Jaune
34 Noir
35 Magenta
36 Cyan

Copiez le code suivant, et mettez le dans votre espace de nom anonyme :

const string KReset   ("0");
const string KNoir    ("30");
const string KRouge   ("31");
const string KVert    ("32");
const string KJaune   ("33");
const string KBleu    ("34");
const string KMAgenta ("35");
const string KCyan    ("36");
	
void Couleur (const string & coul)
{
    cout << "\033[" << coul <<"m";
}	

Le code suivant :

Couleur (KRouge);
cout << "Rouge" << endl;
Couleur (KVert);
cout << "Vert" << endl;
Couleur (KReset);
cout << "Retour à la normale" << endl;

provoquera l’affichage :
Rouge
Vert

Retour à la normale

Changer le fond

Pour changer le fond, c’est exactement la même séquence d’instructions que pour changer la couleur. La seule différence provient du fait que les couleurs associées voient leur code respectif augmenté de 10.

Pour des informations complémentaires quant à la gestion du terminal (sous GNU / Linux), vous pouvez visiter cette page.

M1103 – TP2 – Exercice 2 – Space Invaders

Gestion de la grille

Le but du projet est de réaliser une version simplifiée du célèbre jeu SpaceInvaders).

Les règles du jeu sont les suivantes :

  1. Un unique joueur joue contre un unique envahisseur. Le joueur est toujours sur la ligne du bas de l’écran (dernière ligne de la grille (une matrice de
    caractères)
    représentant l’écran), tandis que l’envahisseur est placé, au début de la partie, en haut de l’écran (la première ligne
    de la grille (la matrice peut être un vector de strings de même taille)).
  2. À chaque fois que c’est son tour de jouer, l’envahisseur avance d’une colonne vers la droite. Lorsqu’il est aux limites de la grille, il descend d’une ligne
    et change de sens (la prochine fois, il se déplacera vers la gauche), et ainsi de suite. Une fois sur 2, il envoie un missile vers le bas
    (le missile part de la colonne où se trouve l’envahisseur et de la ligne suivante). Si le missile touche le joueur, ou si l’envahisseur est arrivé
    en bas de l’écran, le joueur a perdu.
  3. À chaque fois que c’est son tour de jouer, le joueur a 3 possibilités : se déplacer vers la droite (il saisit la touche 6), se déplacer
    vers la gauche (il saisit la touche 4) ou envoyer une torpille (il saisit la touche 5). Si une torpille atteint l’envahisseur, le joueur a gagné.
  4. Le joueur joue plusieurs fois pendant que l’envahisseur ne joue qu’une fois.

La grille est représentée par une matrice de taille KSizeSpace x KSizeLine.
En conséquence, nous pouvons définir les constantes et les alias suivants :

    const char KEmpty               = ' ';  // case vide de l'écran
    const char KRight               = '6';  // déplacement vers la droite
    const char KLeft                = '4';  // Déplacement vers la gauche
    const char KShoot               = '5';  // Lancé de torpille

    //  Constantes liées à l'envahisseur
    
    const string KInvadersColor (KYellow);  // Couleur de l'envahisseur
    const char KInsideInvader       = 'W';  // caractèrere formant l'envahisseur
    const char KMissile             = 'T';  // missile
    const unsigned KInvadersSize    =  4;   // nombre de caractères qui forment l'envahisseur
    const unsigned KInvadersMiddle  = KInvadersSize / 2;
    const string KInvadersForm (KInvadersSize, KInsideInvader);  // forme de l'envahisseur
    
    // Constantes liées au joueur
    
    const string KMyColor (KGreen);
    const char KInsideMe            = 'A';
    const char KTorpedo             = '|';  
    const unsigned KMySize          = 1;
    const unsigned KMyMiddle        = KMySize / 2;
    const string KMyForm (KMySize, KInsideMe);
    
    // Constantes liées à l'eapace (l'écran)
    
    const unsigned KSizeLine   = 10;   // Nombre de lignes de l'écran (de l'espace)
    const unsigned KSizeSpace  = 10;   // Nombre de colonnes de l'écran (de l'espace)
    
    const unsigned KBegInvader = 0;    // Numéro de colonne où commence l'envahisseur
    const unsigned KBegMe      = KSizeLine / 2;  // Numéro de colonne où commence le joueur
    
    typedef vector <string> CVString;    // c'est le type de l'écran (l'espace, la matrice)
    
    const string KEmptyLine (KSizeLine, KEmpty);  // Une ligne vide de la matrice 
    
    const unsigned KRatioMeInvaders = 4;    // Nombre de fois où c'est le tour du joueur pour un tour de l'envahisseur
    

Affichage de la grille

Travail à effectuer : écrire le corps de la fonction DisplaySpace () de profil :

void  DisplaySpace (const CVString & Space)

Cette fonction doit :

  1. faire appel à la fonction ClearScreen ();
  2. afficher case/case le contenu de l’espace (l’écran, la grille). Si la case n’est pas occupée, on affiche
    une case vide, sinon, si c’est une case où se trouve le joueur ou une de ses torpilles, on l’affiche avec la couleur du joueur,
    sinon on l’affiche avec la couleur de l’envahisseur.

M1103 – TP2 – Exercice 3 – Space Invaders

Le jeu

Initialisation de la grille

Ecrire la fonction InitSpace () de profil :

void InitSpace (CVString & Space, unsigned Size);

Cette fonction a pour but d’initialiser toutes les cases de la grille avec le caractère KEmpty ainsi que de placer, sur la première ligne,
l’envahisseur (KInvadersForm) à sa position initiale (KBegInvader) et, sur la dernière ligne, le joueur
(KMyForm) à sa position initiale (KBegMe).

Faire descendre l’envahisseur d’une ligne

Pour gérer le jeu de l’envahisseur et du joueur, il est nécessaire d’écrire quelques outils.

Écrire la fonction DownShift() de profil

void DownShift (CVString & Space, unsigned CurrentLine);

qui fait descendre toutes les lignes de la grile d’une ligne (sauf la dernière) et remplace la première ligne par une ligne vide.

Un joueur est-il mort ?

Écrire le prédicat IsDead() de profil

bool IsDead (const CVString & Space, unsigned Line, unsigned Column, char Who);

qui renvoie vrai si la case de la ligne Line, et de la colonne Column de Space, est une case de l’envahisseur ou du joueur,
mais pas Who et faux sinon.

Tir d’un joueur

Écrire le prédicat Shoot() de profil

bool Shoot (CVString & Space, unsigned Line, unsigned Middle, char Projectile, char Who);

qui renvoie vrai si le tir projeté en ligne Line et en colonne Middle touche directement l’adversaire (utiliser IsDead()),
sinon, place Projectile sur la case Line, Middle et renvoie faux.

Suppression d’un des 2 joueurs

Écrire la fonction Remove() de profil

void Remove (CVString & Space, unsigned Line, unsigned Column);

qui remplace tous les caractères identique à Space [Line][Column],
contigüs, à gauche et à droite de cette case, par des KEmpty.

Recalculer la grille

Lorsque l’envahisseur, d’une part, et le jouieur, d’autre part, ont lancé des missiles et des torpilles, après chaque action d’un des deux joueurs, il faut
faire progresser les missiles (qui descendent d’une ligne) et les torpilles (qui montent d’une ligne) sur la grille.

Écrire la procédure RecomputeSpace() de profil

    void RecomputeSpace (CVString & Space, bool & Win, bool & Lost);

qui déplace Torpilles et Missiles d’une ligne sur la grille. Cette procédure rend vrai Win si une torpille doit toucher l’envahisseur.
Elle rend également vrai Lost si un missile doit toucher le joueur. Elle supprime (Remove) le joueur ou l’envahisseur de sa ligne
s’il a perdu.

Pour vous faciliter le traitement, vous pouvez décomposer en deux procédure, une qui parcours la grille en descendant pour faire progresser les torpilles
(bien qu’elles aillent vers le haut), elle modifie Win et une qui parcours la grille dans l’autre sens pour faire progresser les missiles.

Jeu de l’envahisseur

Écrire le prédicat ManageInvader() de profil

bool ManageInvader (int & Increment, unsigned & CurrentLine,   
                    unsigned & Beg, bool & ToShoot, 
                    bool & Win, CVString & Space);

qui simule je jeu de l’envahisseur comme décrit dans B, renvoie vrai lorsque l’envahisseur a gagné et faux sinon.

  • Increment vaut 1 ou -1, suivant que l’envahisseur va vers la droite ou vers la gauche, il s’inverse en bout de ligne.
  • CurrentLine est le numéro de la ligne où se trouve l’envahisseur avant son déplacement. Incrémenté de 1 en bout de
    ligne.
  • Beg indique la colonne où se trouve le début de l’envahisseur, incrémenté de Increment sauf si en bout de ligne.
  • ToShoot s’inverse à chaque coup. Si vrai l’envahisseur tire un missile après son déplacement.
  • Win devient vrai si l’envahisseur doit occuper une position occupée par une torpille.
  • Space le grille

Jeu du joueur

Écrire le prédicat ManageMe() de profil

bool ManageMe (CVString & Space, unsigned & Pos, bool & Lost);

qui simule je jeu du joueur comme décrit dans B, renvoie vrai lorsque le joueur a gagné et faux sinon. C’est ici que le joueur va choisir ce qu’il fait.
Renvoie vrai si le joueur a gagné, faux sinon.

  • Space Le grille
  • Pos Position du joueur (sur sa dernière ligne), avant et aprè avoir joué.
  • Lost devient vrai si le joueur a perdu.

L’algorithme principal

Écrire la procédure SpaceInvaders() de profil

void SpaceInvaders (void);

qui :

  • d&ecute;clare une grille ;
  • l’initialise (InitSpace() ;
  • initialise le sens de déplacement initial de l’envahisseur, sa ligne courante, sa position initiale, celle du joueur, le fait que le joueur a gagné,
    qu’il a perdu, et que l’envahisseur doit tirer, tous les 3 à faux ;
  • affiche l’espace (DisplaySpace()) ;
  • dans une boucle infinie (on en sortira dès que l’un des deux joueurs aura gagné)

    • boucle pour faire jouer KRatioMeInvaders fois le joueur, boucle dans laquelle le joueur joue, s’il n’a pas gagné on recalcule
      la grille (RecomputeSpace()), on affiche la grille et on sort de cette boucle si le joueur a gagné ;
    • on sort si l’un des deux joueurs a gagné ;
    • l’envahisseur joue ;
    • si aucun des deux joueurs n’a gagn&eaucte;, on recalcule l’espace ;
    • on affiche la grille.
  • on affiche le résultat de la partie