mirror of
https://github.com/kierankihn/uno-game.git
synced 2025-12-27 02:13:18 +08:00
refactor(game): introduce draw and play methods in PlayerState and subclasses
- Replaced `setRemainingCardCount` with `draw` and `play` methods. - Added virtual overrides for player-specific behaviors in `ClientPlayerState` and `ServerPlayerState`. - Refactored `ServerGameState::init` to centralize deck and discard pile setup. - Updated `updateStateByDraw` to leverage `PlayerState::draw` for consistency.
This commit is contained in:
@@ -15,7 +15,6 @@ namespace UNO::GAME {
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string PlayerState::getName() const
|
std::string PlayerState::getName() const
|
||||||
{
|
{
|
||||||
return this->name_;
|
return this->name_;
|
||||||
@@ -30,59 +29,100 @@ namespace UNO::GAME {
|
|||||||
{
|
{
|
||||||
return this->remainingCardCount_;
|
return this->remainingCardCount_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerState::setRemainingCardCount(size_t x)
|
|
||||||
{
|
|
||||||
this->remainingCardCount_ = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlayerState::setIsUno(bool x)
|
void PlayerState::setIsUno(bool x)
|
||||||
{
|
{
|
||||||
this->isUno_ = x;
|
this->isUno_ = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlayerState::draw(size_t n, const std::vector<Card> &cards)
|
||||||
|
{
|
||||||
|
this->remainingCardCount_ += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
Card PlayerState::play(const Card &card)
|
||||||
|
{
|
||||||
|
this->remainingCardCount_--;
|
||||||
|
return card;
|
||||||
|
}
|
||||||
|
|
||||||
ClientPlayerState::ClientPlayerState(std::string name, size_t remainingCardCount, bool isUno) :
|
ClientPlayerState::ClientPlayerState(std::string name, size_t remainingCardCount, bool isUno) :
|
||||||
PlayerState(std::move(name), remainingCardCount, isUno)
|
PlayerState(std::move(name), remainingCardCount, isUno)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerPlayerState::ServerPlayerState(std::string name, size_t remainingCardCount, bool isUno, HandCard *handCard) :
|
void ClientPlayerState::draw(size_t n, const std::vector<Card> &cards)
|
||||||
PlayerState(std::move(name), remainingCardCount, isUno), handCard(handCard)
|
|
||||||
{
|
{
|
||||||
|
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<Card> &ServerPlayerState::getCards() const
|
||||||
|
{
|
||||||
|
return this->handCard_.getCards();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerPlayerState::draw(size_t x, const std::vector<Card> &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)) {}
|
ClientGameState::ClientGameState(GameStatus gameStatus, Player player) : GameState(gameStatus), player(std::move(player)) {}
|
||||||
|
|
||||||
ServerGameState::ServerGameState() : GameState(GameStatus::WAITING_PLAYERS_TO_JOIN) {}
|
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) {
|
deck_.clear(), discardPile_.clear();
|
||||||
throw std::invalid_argument("Card cannot be played");
|
while (discardPile_.isEmpty() || discardPile_.getFront().getType() > CardType::NUM9) {
|
||||||
|
discardPile_.add(deck_.draw());
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto &handCardSet = this->getCurrentPlayer()->handCard->getCards();
|
for (size_t i = 0; i < 7; i++) {
|
||||||
for (auto it = handCardSet.begin(); ; it++) {
|
for (auto &player : this->players_) {
|
||||||
if (it == handCardSet.end()) {
|
player.draw(1, this->deck_.draw(1));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GameState::updateStateByCard(card);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ServerGameState::updateStateByDraw()
|
void ServerGameState::updateStateByDraw()
|
||||||
{
|
{
|
||||||
if (this->drawCount_ == 0) {
|
if (this->drawCount_ == 0) {
|
||||||
this->drawCount_ = 1;
|
this->drawCount_ = 1;
|
||||||
}
|
}
|
||||||
this->currentPlayer_->handCard->draw(this->deck_.draw(this->drawCount_));
|
this->currentPlayer_->draw(this->drawCount_, deck_.draw(this->drawCount_));
|
||||||
|
this->drawCount_ = 0;
|
||||||
GameState::updateStateByDraw();
|
this->nextPlayer();
|
||||||
}
|
}
|
||||||
} // namespace UNO::GAME
|
} // namespace UNO::GAME
|
||||||
@@ -23,9 +23,11 @@ namespace UNO::GAME {
|
|||||||
size_t remainingCardCount_;
|
size_t remainingCardCount_;
|
||||||
bool isUno_;
|
bool isUno_;
|
||||||
|
|
||||||
public:
|
|
||||||
PlayerState(std::string name, size_t remainingCardCount, bool isUno);
|
PlayerState(std::string name, size_t remainingCardCount, bool isUno);
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~PlayerState() = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return 玩家名字
|
* @return 玩家名字
|
||||||
*/
|
*/
|
||||||
@@ -41,35 +43,80 @@ namespace UNO::GAME {
|
|||||||
*/
|
*/
|
||||||
[[nodiscard]] size_t getRemainingCardCount() const;
|
[[nodiscard]] size_t getRemainingCardCount() const;
|
||||||
|
|
||||||
/**
|
|
||||||
* 将剩余手牌设置为 x 张
|
|
||||||
* @param x 要设置的张数
|
|
||||||
*/
|
|
||||||
void setRemainingCardCount(size_t x);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置 Uno 状态
|
* 设置 Uno 状态
|
||||||
* @param x Uno 状态
|
* @param x Uno 状态
|
||||||
*/
|
*/
|
||||||
void setIsUno(bool x);
|
void setIsUno(bool x);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 摸牌
|
||||||
|
* @param n 摸的张数
|
||||||
|
* @param cards 摸到的牌
|
||||||
|
*/
|
||||||
|
void virtual draw(size_t n, const std::vector<Card> &cards);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 出一张牌
|
||||||
|
*/
|
||||||
|
Card virtual play(const Card &card);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (供客户端使用)玩家状态
|
* (供客户端使用)玩家状态
|
||||||
*/
|
*/
|
||||||
class ClientPlayerState : public PlayerState {
|
class ClientPlayerState final : public PlayerState {
|
||||||
public:
|
public:
|
||||||
ClientPlayerState(std::string name, size_t remainingCardCount, bool isUno);
|
ClientPlayerState(std::string name, size_t remainingCardCount, bool isUno);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 摸牌
|
||||||
|
* @param n 摸的张数
|
||||||
|
* @param cards 摸的牌
|
||||||
|
*/
|
||||||
|
void draw(size_t n, const std::vector<Card> &cards) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 出一张牌
|
||||||
|
*/
|
||||||
|
Card play(const Card &card) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (供服务端使用)玩家状态
|
* (供服务端使用)玩家状态
|
||||||
*/
|
*/
|
||||||
class ServerPlayerState : public PlayerState {
|
class ServerPlayerState final : public PlayerState {
|
||||||
public:
|
private:
|
||||||
explicit ServerPlayerState(std::string name, size_t remainingCardCount, bool isUno, HandCard *handCard);
|
HandCard handCard_;
|
||||||
|
|
||||||
HandCard *handCard;
|
public:
|
||||||
|
explicit ServerPlayerState(std::string name, size_t remainingCardCount, bool isUno);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得当前手牌
|
||||||
|
* @return 当前手牌的集合
|
||||||
|
*/
|
||||||
|
[[nodiscard]] const std::multiset<Card> &getCards() const;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 摸牌
|
||||||
|
* @param x 摸的张数
|
||||||
|
* @param cards 摸的牌
|
||||||
|
*/
|
||||||
|
void draw(size_t x, const std::vector<Card> &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) {
|
if (this->discardPile_.isEmpty() == false && card.canBePlayedOn(this->discardPile_.getFront()) == false) {
|
||||||
throw std::invalid_argument("Card cannot be played");
|
throw std::invalid_argument("Card cannot be played");
|
||||||
}
|
}
|
||||||
this->currentPlayer_->setRemainingCardCount(this->currentPlayer_->getRemainingCardCount() - 1);
|
this->currentPlayer_->play(card);
|
||||||
if (card.getType() == CardType::DRAW2) {
|
if (card.getType() == CardType::DRAW2) {
|
||||||
this->drawCount_ += 2;
|
this->drawCount_ += 2;
|
||||||
}
|
}
|
||||||
@@ -264,7 +311,7 @@ namespace UNO::GAME {
|
|||||||
if (this->drawCount_ == 0) {
|
if (this->drawCount_ == 0) {
|
||||||
this->drawCount_ = 1;
|
this->drawCount_ = 1;
|
||||||
}
|
}
|
||||||
this->currentPlayer_->setRemainingCardCount((this->currentPlayer_->getRemainingCardCount() + this->drawCount_));
|
this->currentPlayer_->draw(this->drawCount_, {});
|
||||||
this->drawCount_ = 0;
|
this->drawCount_ = 0;
|
||||||
this->nextPlayer();
|
this->nextPlayer();
|
||||||
}
|
}
|
||||||
@@ -284,10 +331,9 @@ namespace UNO::GAME {
|
|||||||
ServerGameState();
|
ServerGameState();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 由于用户出牌而改变状态
|
* 开始游戏
|
||||||
* @param card 用户出的牌
|
|
||||||
*/
|
*/
|
||||||
void updateStateByCard(const Card &card) override;
|
void init();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 由于用户摸牌而改变状态
|
* 由于用户摸牌而改变状态
|
||||||
|
|||||||
Reference in New Issue
Block a user