Chapitre 2 • classes, abstractions
Cartouche
| Champ | Valeur |
|---|---|
| Auteur·e | Élise |
| Édition | 2023-09-15 |
| Durée | une journée |
| Taille des équipes | 1 personne |
| Rendu | via git, dépôt 2023_cpp_c2, droits en lecture à delivery_collector |
Barème
| Critère | Points |
|---|---|
| AsciiMap construction avec param. | 3 |
| Champs privés | 1 |
| AsciiMap comportement | 8 |
| AsciiMapClip construction avec ref. | 3 |
| AsciiMapClip comportement | 5 |
| Gestion d’erreur | 3 |
| Total des critères | 23 |
| Note maximale | 20 |
| Fautes de norme | -0,5 par ligne |
Règlement
La réalisation de cet exercice est assujettie aux règles en vigueur dans l’école en matière de triche et de normalisation. Tricher vous expose à de graves sanctions.
Vous devez être seul·e auteur·e de votre rendu mais vous êtes autorisés et encouragés à communiquer dans le cadre de ce sujet.
Dépôt de référence et norme
Dépôt de référence avec règles clang format.
Introduction
Votre objectif aujourd’hui c’est de préparer des classes pour faciliter l’implémentation d’un jeu textuel.
Ce que vous allez implémenter c’est une classe qui permet de manipuler une carte de jeu dont chacune des cases contient un caractère ASCII. Les problématiques soulevées sont similaires à celle de travailler avec un tableau de pixel (sur une dimension) tout en permettant de placer un caractère à l’aide de coordonnées en 2 dimensions. Enfin, ça, c’est à vous de voir, car vous êtes libres de votre implémentation dès lors qu’elle répond aux exigences fixées par ce sujet.
Vous allez aussi devoir implémenter un clip de votre carte. C’est à dire une deuxième classe qui se construit avec la première, mais qui permet de regarder et de modifier une sous-section précise de la map. Si ça n’est pas tout de suite clair pensez std::string_view et faites bien attentions aux exemples qui vous sont donnés.
Tâches
AsciiMap
Fichiers à rendre : AsciiMap.cpp, AsciiMap.hpp, AsciiMap.main.cpp
Consigne
Vous devez implémenter une classe AsciiMap qui doit répondre aux exigences suivantes :
- construction avec deux nombres en paramètre, la largeur et la hauteur de la carte
- après la construction votre carte doit être prête à l’usage
- fonction membre
set_cellavec trois paramètres :- position x
- position y
- caractère à placer dans la case
- fonction membre
get_cellqui renvoie la valeur d’une case, prend en paramètre les coordonnées x et y de la case - fonction membre
to_streamqui prend en paramètre un flux en sortie, et qui y affiche le contenu de la carte - fonction
widthqui permet d’obtenir la largeur de la map - fonction
heightqui permet d’obtenir la hauteur de la map
Rendez aussi un fichier AsciiMap.main.cpp qui contient un main qui teste votre classe et démontre la façon dont on peut s’en servir.
Exemple
Code d’exemple :
#include <iostream>
#include "AsciiMap.hpp"
void mk_line(AsciiMap &map, unsigned int y)
{
auto i{0U};
while (i < map.width()) {
if (map.get_cell(i, y) == '|') {
map.set_cell(i, y, '+');
} else {
map.set_cell(i, y, '-');
}
i += 1;
}
}
void mk_col(AsciiMap &map, unsigned int x)
{
auto i{0U};
while (i < map.height()) {
if (map.get_cell(x, i) == '-') {
map.set_cell(x, i, '+');
} else {
map.set_cell(x, i, '|');
}
i += 1;
}
}
int main(void)
{
AsciiMap map{11, 11};
mk_line(map, 3);
mk_line(map, 7);
mk_col(map, 3);
mk_col(map, 7);
map.to_stream(std::cout);
}
Sortie attendue :
| |
| |
| |
---+---+---
| |
| |
| |
---+---+---
| |
| |
| |
AsciiMapClip
Fichiers que vous pouvez modifier : AsciiMap.cpp, AsciiMap.hpp, AsciiMap.main.cpp
Nouveaux fichiers à rendre : AsciiMapClip.cpp, AsciiMapClip.hpp, AsciiMapClip.main.cpp
Consignes
Il s’agit d’une classe dont le rôle et de permettre l’observation et la modification d’une AsciiMap mais en partant d’une origine différente de .
Cela permet de faciliter le dessin d’un même motif à plusieurs endroit sur une même AsciiMap sans que la fonction chargée du dessin n’ai besoin de savoir où l’on souhaite dessiner. On évite aussi de se répéter dans toutes les fonctions de dessins avec le code nécessaire à un changement d’origine.
Par exemple : si on choisi pour origine il faudra ajouter aux et 3 aux de tous les appels à get_cell et set_cell.
Votre Clip doit répondre aux exigences suivantes :
- construction avec une référence sur une
AsciiMapet stockage de cette référence dans les champs de la classe - fonction membre
set_origin, paramètres x et y à utiliser en origine à la place de - fonction membre
set_size- paramètres x et y
- donnent la valeur max que x et y peuvent avoir dans les appels à
set_celletget_cell
- fonction membre
set_cell, paramètres x, y et caractère- prend en compte l’origine et la taille définies par
set_originetset_size - assigne à l’emplacement le caractère donné
- prend en compte l’origine et la taille définies par
- fonction membre
get_cell- prend en compte l’origine et la taille définies par
set_originetset_size - renvoie le caractère à l’emplacement
- prend en compte l’origine et la taille définies par
Exemple
void draw_o(AsciiMapClip &clip)
{
clip.set_cell(1,0,'-');
clip.set_cell(0,1,'|');
clip.set_cell(2,1,'|');
clip.set_cell(1,2,'-');
}
void draw_x(AsciiMapClip &clip)
{
clip.set_cell(0, 0, '\\');
clip.set_cell(2, 2, '\\');
clip.set_cell(1, 1, 'X');
clip.set_cell(2, 0, '/');
clip.set_cell(0, 2, '/');
}
int main(void)
{
AsciiMap map{11, 11};
AsciiMapClip TopLeft(map), TopRight(map), TopCenter(map);
TopCenter.set_origin(4, 0);
TopCenter.set_size(3, 3);
TopRight.set_origin(8, 0);
TopRight.set_size(3, 3);
mk_line(map, 3);
mk_line(map, 7);
mk_col(map, 3);
mk_col(map, 7);
draw_o(TopCenter);
draw_x(TopRight);
map.to_stream(std::cout);
}
Sortie attendue :
| - |\ /
|| || X
| - |/ \
---+---+---
| |
| |
| |
---+---+---
| |
| |
| |
Gestion d’erreur
Parmi les fonctions membres que vous avez programmé sur les classes précédentes, plusieurs d’entre elles peuvent échouer à leur tâche.
Si vous y avez fait attention, vous avez peut-être déjà mis des conditions pour empêcher une tentative de changer ou de lire une case dont les coordonnées vont au delà de la largeur et hauteur de votre Map ou de votre Clip.
En plus d’une protection, ce que l’on peut faire c’est ajouter des exceptions.
int main(void)
{
AsciiMap map(5, 5);
try {
map.set_cell(5, 5, 'a');
std::cout << "it shouldn't have workded\n";
} catch (std::exception &err) {
std::cerr << err.what() << std::endl;
}
}
Dans AsciiMap et AsciiMapClip ajoutez des exceptions lorsque des coordonnées vous sont données en dehors.