diff --git a/src/game/GameState.cpp b/src/game/GameState.cpp index ef35d22..8d6d214 100644 --- a/src/game/GameState.cpp +++ b/src/game/GameState.cpp @@ -15,7 +15,6 @@ namespace UNO::GAME { { } - std::string PlayerState::getName() const { return this->name_; @@ -30,59 +29,100 @@ namespace UNO::GAME { { return this->remainingCardCount_; } - - void PlayerState::setRemainingCardCount(size_t x) - { - this->remainingCardCount_ = x; - } - void PlayerState::setIsUno(bool x) { this->isUno_ = x; } + void PlayerState::draw(size_t n, const std::vector &cards) + { + this->remainingCardCount_ += n; + } + + Card PlayerState::play(const Card &card) + { + this->remainingCardCount_--; + return card; + } + ClientPlayerState::ClientPlayerState(std::string name, size_t remainingCardCount, bool isUno) : PlayerState(std::move(name), remainingCardCount, isUno) { } - ServerPlayerState::ServerPlayerState(std::string name, size_t remainingCardCount, bool isUno, HandCard *handCard) : - PlayerState(std::move(name), remainingCardCount, isUno), handCard(handCard) + void ClientPlayerState::draw(size_t n, const std::vector &cards) { + PlayerState::draw(n, cards); + } + + Card ClientPlayerState::play(const Card &card) + { + return PlayerState::play(card); + } + + ServerPlayerState::ServerPlayerState(std::string name, size_t remainingCardCount, bool isUno) : + PlayerState(std::move(name), remainingCardCount, isUno) + { + } + + const std::multiset &ServerPlayerState::getCards() const + { + return this->handCard_.getCards(); + } + + void ServerPlayerState::draw(size_t x, const std::vector &cards) + { + PlayerState::draw(x, cards); + this->handCard_.draw(cards); + } + + + Card ServerPlayerState::play(const Card &card) + { + PlayerState::play(card); + for (auto it = this->handCard_.getCards().begin();; it++) { + if (it == this->handCard_.getCards().end()) { + throw std::invalid_argument("Card not found in hand"); + } + if (card.getType() == it->getType() + && (card.getType() == CardType::WILD || card.getType() == CardType::WILDDRAWFOUR || card.getColor() == it->getColor())) { + this->handCard_.play(it); + break; + } + } + return PlayerState::play(card); + } + + bool ServerPlayerState::isEmpty() const + { + return this->handCard_.isEmpty(); } ClientGameState::ClientGameState(GameStatus gameStatus, Player player) : GameState(gameStatus), player(std::move(player)) {} ServerGameState::ServerGameState() : GameState(GameStatus::WAITING_PLAYERS_TO_JOIN) {} - void ServerGameState::updateStateByCard(const Card &card) + void ServerGameState::init() { - if (this->discardPile_.isEmpty() == false && card.canBePlayedOn(this->discardPile_.getFront()) == false) { - throw std::invalid_argument("Card cannot be played"); + deck_.clear(), discardPile_.clear(); + while (discardPile_.isEmpty() || discardPile_.getFront().getType() > CardType::NUM9) { + discardPile_.add(deck_.draw()); } - const auto &handCardSet = this->getCurrentPlayer()->handCard->getCards(); - for (auto it = handCardSet.begin(); ; it++) { - if (it == handCardSet.end()) { - throw std::invalid_argument("Card not found in hand"); - } - if (card.getType() == it->getType() && (card.getType() == CardType::WILD || card.getType() == CardType::WILDDRAWFOUR || card.getColor() == it->getColor())) { - this->getCurrentPlayer()->handCard->play(it); - break; + for (size_t i = 0; i < 7; i++) { + for (auto &player : this->players_) { + player.draw(1, this->deck_.draw(1)); } } - - GameState::updateStateByCard(card); } - void ServerGameState::updateStateByDraw() { if (this->drawCount_ == 0) { this->drawCount_ = 1; } - this->currentPlayer_->handCard->draw(this->deck_.draw(this->drawCount_)); - - GameState::updateStateByDraw(); + this->currentPlayer_->draw(this->drawCount_, deck_.draw(this->drawCount_)); + this->drawCount_ = 0; + this->nextPlayer(); } } // namespace UNO::GAME \ No newline at end of file diff --git a/src/game/GameState.h b/src/game/GameState.h index 855ab83..7cae6a4 100644 --- a/src/game/GameState.h +++ b/src/game/GameState.h @@ -23,9 +23,11 @@ namespace UNO::GAME { size_t remainingCardCount_; bool isUno_; - public: PlayerState(std::string name, size_t remainingCardCount, bool isUno); + public: + virtual ~PlayerState() = default; + /** * @return 玩家名字 */ @@ -41,35 +43,80 @@ namespace UNO::GAME { */ [[nodiscard]] size_t getRemainingCardCount() const; - /** - * 将剩余手牌设置为 x 张 - * @param x 要设置的张数 - */ - void setRemainingCardCount(size_t x); - /** * 设置 Uno 状态 * @param x Uno 状态 */ void setIsUno(bool x); + + /** + * 摸牌 + * @param n 摸的张数 + * @param cards 摸到的牌 + */ + void virtual draw(size_t n, const std::vector &cards); + + /** + * 出一张牌 + */ + Card virtual play(const Card &card); }; /** * (供客户端使用)玩家状态 */ - class ClientPlayerState : public PlayerState { + class ClientPlayerState final : public PlayerState { public: ClientPlayerState(std::string name, size_t remainingCardCount, bool isUno); + + /** + * 摸牌 + * @param n 摸的张数 + * @param cards 摸的牌 + */ + void draw(size_t n, const std::vector &cards) override; + + /** + * 出一张牌 + */ + Card play(const Card &card) override; }; /** * (供服务端使用)玩家状态 */ - class ServerPlayerState : public PlayerState { - public: - explicit ServerPlayerState(std::string name, size_t remainingCardCount, bool isUno, HandCard *handCard); + class ServerPlayerState final : public PlayerState { + private: + HandCard handCard_; - HandCard *handCard; + public: + explicit ServerPlayerState(std::string name, size_t remainingCardCount, bool isUno); + + /** + * 获得当前手牌 + * @return 当前手牌的集合 + */ + [[nodiscard]] const std::multiset &getCards() const; + + + /** + * 摸牌 + * @param x 摸的张数 + * @param cards 摸的牌 + */ + void draw(size_t x, const std::vector &cards) override; + + /** + * 打出一张牌 + * @param card 要打出的手牌 + * @return 打出的手牌 + */ + Card play(const Card &card) override; + + /** + * @return 手牌是否为空 + */ + [[nodiscard]] bool isEmpty() const; }; /** @@ -241,7 +288,7 @@ namespace UNO::GAME { if (this->discardPile_.isEmpty() == false && card.canBePlayedOn(this->discardPile_.getFront()) == false) { throw std::invalid_argument("Card cannot be played"); } - this->currentPlayer_->setRemainingCardCount(this->currentPlayer_->getRemainingCardCount() - 1); + this->currentPlayer_->play(card); if (card.getType() == CardType::DRAW2) { this->drawCount_ += 2; } @@ -264,7 +311,7 @@ namespace UNO::GAME { if (this->drawCount_ == 0) { this->drawCount_ = 1; } - this->currentPlayer_->setRemainingCardCount((this->currentPlayer_->getRemainingCardCount() + this->drawCount_)); + this->currentPlayer_->draw(this->drawCount_, {}); this->drawCount_ = 0; this->nextPlayer(); } @@ -284,10 +331,9 @@ namespace UNO::GAME { ServerGameState(); /** - * 由于用户出牌而改变状态 - * @param card 用户出的牌 + * 开始游戏 */ - void updateStateByCard(const Card &card) override; + void init(); /** * 由于用户摸牌而改变状态