Projet Dominion en C++
Projet de Développement Logiciel et d'Architecture Orientée Objet
Ce projet académique est une implémentation en C++ du célèbre jeu de deck-building Dominion. L'objectif était d'appliquer les concepts de programmation orientée objet (héritage, polymorphisme) et de C++ moderne (pointeurs intelligents) pour créer un moteur de jeu complet, jouable en console.
Fonctionnalités Clés
- Moteur de Jeu Complet : Gestion des phases de jeu (Action, Achat, Ajustement), des decks, des mains et des défausses.
- Multijoueur (2-4 joueurs) : Le jeu est conçu pour être joué par 2, 3 ou 4 joueurs humains.
- Intelligence Artificielle (IA) : Possibilité de remplacer un joueur par une IA avec une stratégie de base.
- Système de Sauvegarde et Chargement : Les joueurs peuvent sauvegarder une partie et la reprendre plus tard via un fichier CSV.
- Sélection de Cartes Personnalisée : Choix des 10 cartes "Action" qui composeront la réserve du jeu.
- Interface Console Stylisée : Utilisation de couleurs pour différencier les types de cartes et améliorer la lisibilité de l'interface en terminal.
Galerie d'Images



Architecture Orientée Objet et C++ Moderne
Le cœur du projet repose sur une architecture robuste pour modéliser les différentes composantes du jeu, en suivant les bonnes pratiques du C++.
- Séparation Interface/Implémentation (.h/.cpp) : Chaque classe est définie avec un fichier d'en-tête (
.h
) pour l'interface et un fichier source (.cpp
) pour l'implémentation, garantissant la modularité. - Héritage et Polymorphisme (`Carte`) : Une classe de base
Carte
a été créée, avec des classes dérivées (CarteTresor
,CarteAction
, etc.), permettant de manipuler toutes les cartes de manière polymorphique. - Gestion de la Mémoire (`std::shared_ptr`) : Pour éviter les fuites de mémoire et simplifier la gestion de la durée de vie des objets, j'ai utilisé des pointeurs intelligents (
std::shared_ptr
) partout dans le projet. - Classes Principales :
Joueur
: Gère l'état d'un joueur (deck, main, défausse).PlateauJeu
: Agit comme le contrôleur principal du jeu, gérant le déroulement des tours et la réserve de cartes.
Extraits de Code
1. Polymorphisme et Affichage en Console (`Carte.cpp`)
Cette méthode virtuelle Afficher()
permet à chaque type de carte de s'afficher différemment, notamment avec une couleur spécifique.
// Extrait de Carte.cpp
void Carte::Afficher() const {
const std::string RESET = "\033[0m";
const std::string GREEN = "\033[92m"; // Victoire
const std::string YELLOW = "\033[93m"; // Trésor
// ... autres couleurs
std::string couleur;
if (type == "victoire") {
couleur = GREEN;
} else if (type == "tresor") {
couleur = YELLOW;
} // ...
std::cout << couleur << " - Nom : " << getNom()
<< " | Prix : " << getPrix()
<< " | Type : " << getType() << RESET;
}
2. Logique d'une Carte Action (`CarteAction.cpp`)
Chaque carte "Action" possède sa propre méthode d'exécution. Voici l'exemple de la "Sorcière", qui affecte le joueur actif et ses adversaires.
// Extrait de CarteAction.cpp
void CarteAction::executerActionSorciere(std::shared_ptr<Joueur> j){
std::cout << "\n Effet Sorciere : Piochez 2 cartes...";
for (int i=0; i<2; i++){
j->ajouterCarteMain();
j->retirerCarteDeck();
}
}
void CarteAction::executerActionSorciere2(std::shared_ptr<Joueur> adversaire, PlateauJeu* pj){
// Logique pour ajouter une carte Malédiction à l'adversaire
// ...
}
Défis Rencontrés et Solutions
- Problème : Gestion du polymorphisme et du casting. Le casting entre pointeurs de base et dérivés était risqué.
Solution : L'adoption destd::shared_ptr
etstd::dynamic_pointer_cast
a permis un casting sécurisé et une gestion de la mémoire automatique. - Problème : Mise à jour de l'état des joueurs. Sans pointeurs, les modifications sur un joueur n'étaient pas répercutées partout.
Solution : L'utilisation destd::shared_ptr<Joueur>
a garanti que toutes les parties du code manipulaient une seule et même instance de chaque joueur.
Pour consulter l'intégralité du code source de ce projet, rendez-vous sur mon dépôt GitHub.
Voir le projet sur GitHub