1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
| /* Pour jouer aux cartes, on a besoin ... de cartes ... */
class Card{
/* tu y mets ce que tu veux ici, mais les cartes auront sémantique d'entité
* car tu as les cartes "classiques", les tarots, et plein d'autres sortes de
* jeux de cartes ;)
*/
public:
Card() = default;
Card(Card const &) = delete;
Card & operator = (Card const &) = delete;
virtual ~Card() = default;
};
/* Le système de distribution des cartes */
class Distributor{
/* pour la facilité, parce que le nom complet est très long */
using stack_t = std::vector<std::reference_wrapper<const Card>>;
public:
/* lui aussi, il a sémantique d'entité,
* même si il n'est pas destiné à être dérivé
*/
Distributor() = default;
Distributor(Distributor const &) = delete;
Distributor& operator = (Distributor const &) = delete;
~Distributor() = default;
/* Le distributeur va agir comme une collection classique,
* en permettant
* - l'ajout
* - l'accès à celle qui se trouve "en haut" de la pile
* - la suppression de celle qui se trouve en haut de la pile
* - la suppression de toutes les cartes
* - le mélange des cartes qu'il contient (car cela peut être utile :D )
* - de savoir s'il contient ne serait-ce qu'une carte
*/
void push(Card const & card){
stack_.emplace_back(card);
}
Card const & top(){
assert(current_ < stack_.size() && "Distributor is empty!");
return stack_[current_].get();
}
void pop(){
assert(current_ < stack_.size() && "Distributor is empty!");
++ current_;
}
void clear(){
current_ = 0;
stack_.clear();
}
bool empty() const{
return stack_.empty() || current_ >= stack_.size();
}
void shuffle(){
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(stack_.begin(), stack_.end(), g);
}
private:
stack_t stack_;
size_t current_{0};
};
/* Nous avons les "jeux" (paquets) de cartes ...
* ce sont les propriétaires des cartes qu'ils contiennent
*/
class CardPack{
/* par facilité */
using pack_t = std::vector<std::unique_ptr<Card>>;
public:
/* ils ont -- forcément -- sémantique d'entité
*/
CardPack(); // il construisent les cartes dont ils ont besoin ici
CardPack(CardPack const &) = delete;
CardPack & operator = (CardPack const &) = delete;
virtual ~CardPack() = default;
/* Tout ce que l'on attend de leur part, c'est d'être en mesure
* de placer les cartes dans le sabot
*/
void fillDistributor(Distributor & d){
assert(!inDistributor_ && "Already put in a distributor!");
for(auto const & it : pack_){
d.push(*it.get());
}
inDistributor_ = true;
}
private:
bool inDistributor_{false};
pack_t pack_;
};
/* Et, enfin, on a le joueur */
class Gamer{
/* par facilité */
using hand_t = std::vector<std::reference_wrapper<const Card>>;
public:
/* il a -- forcément -- sémantique d'entité */
Gamer() = default;
Gamer(Gamer const &) = delete;
Gamer & operator = (Gamer const & ) = delete;
virtual ~Gamer() = default;
/* il peut piocher une carte dans le sabot */
bool draw(Distributor & d){
if(! d.empty()){
auto const & card = d.top();
d.pop();
hand_.emplace_back(card);
return true;
}
return false;
}
/* il pourra sans doute faire d'autres choses...
* avec toutes ses cartes ... à toi de les définir
*/
private:
hand_t hand_;
};
/* enfin, il y a le jeu en lui-même, qui est le propriétaire légitime:
* - de tous les paquets de cartes utilisés
* - de tous les joueurs en présence
* - de tous les sabots mis à disposition
*/
class Game{
public:
/*quelques fonctionalités intéressantes */
/* ajouter un paquet de cartes */
void addPack(){
packs_.emplace_back(std::make_unique<CardPack>());
/* on choisi le distributeur dans lequel placer le paquet créé
* (à toi de voir comment faire)
*/
auto & pack = packs_.front();
pack->fillDistributor(chosenDistributor);
}
/* et bien sur, il doit s'exécuter */
void run(){
/* ... */
}
/* et tout le reste, bien sur ! */
private:
std::vector<std::unique_ptr<Distributor>> distributors_;
std::vector<std::unique_ptr<CardPack>> packs_;
std::vector<std::unique_ptr<Gamer>> gamers_;
}; |
Partager