mirror of
https://github.com/kierankihn/uno-game.git
synced 2025-12-27 02:13:18 +08:00
refractor(game): enhance state management with clear and endGame methods
- Added `clear` methods to `PlayerState`, `ServerPlayerState`, and `HandCard`. - Introduced `endGame` methods to `GameState`, `ClientGameState`, and `ServerGameState`. - Improved `init` and `nextPlayer` logic in `ClientGameState`. - Added `getClientGameStage` and `getServerGameStage` methods to retrieve game stages.
This commit is contained in:
@@ -46,6 +46,11 @@ namespace UNO::GAME {
|
|||||||
return card;
|
return card;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlayerState::clear()
|
||||||
|
{
|
||||||
|
this->remainingCardCount_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
@@ -84,16 +89,48 @@ namespace UNO::GAME {
|
|||||||
return this->handCard_.isEmpty();
|
return this->handCard_.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientGameState::ClientGameState(std::string name) : player_(std::move(name)) {}
|
void ServerPlayerState::clear()
|
||||||
|
{
|
||||||
|
PlayerState::clear();
|
||||||
|
this->handCard_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientGameState::ClientGameState(std::string name) : player_(std::move(name)), clientGameStage_(ClientGameStage::PENDING_CONNECTION) {}
|
||||||
|
|
||||||
|
void ClientGameState::nextPlayer()
|
||||||
|
{
|
||||||
|
GameState::nextPlayer();
|
||||||
|
if (this->self_ == this->currentPlayer_) {
|
||||||
|
this->clientGameStage_ = ClientGameStage::ACTIVE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->clientGameStage_ = ClientGameStage::IDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const std::multiset<Card> &ClientGameState::getCards() const
|
const std::multiset<Card> &ClientGameState::getCards() const
|
||||||
{
|
{
|
||||||
return this->player_.getCards();
|
return this->player_.getCards();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientGameState::init(DiscardPile discardPile)
|
void ClientGameState::init(const std::vector<ClientPlayerState> &players,
|
||||||
|
const DiscardPile &discardPile,
|
||||||
|
const std::multiset<Card> &handCard,
|
||||||
|
const size_t ¤tPlayerIndex,
|
||||||
|
const size_t &selfIndex)
|
||||||
{
|
{
|
||||||
this->discardPile_ = std::move(discardPile);
|
this->players_ = players;
|
||||||
|
this->discardPile_ = discardPile;
|
||||||
|
player_.draw(std::vector<Card>(handCard.begin(), handCard.end()));
|
||||||
|
this->currentPlayer_ = this->players_.begin() + static_cast<int>(currentPlayerIndex);
|
||||||
|
this->self_ = this->players_.begin() + static_cast<int>(selfIndex);
|
||||||
|
if (this->self_ == this->currentPlayer_) {
|
||||||
|
this->clientGameStage_ = ClientGameStage::ACTIVE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->clientGameStage_ = ClientGameStage::IDLE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -117,26 +154,32 @@ namespace UNO::GAME {
|
|||||||
return this->player_.isEmpty();
|
return this->player_.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerGameState::ServerGameState() = default;
|
ClientGameStage ClientGameState::getClientGameStage() const
|
||||||
|
{
|
||||||
|
return this->clientGameStage_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientGameState::endGame()
|
||||||
|
{
|
||||||
|
this->clientGameStage_ = ClientGameStage::PRE_GAME;
|
||||||
|
this->player_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerGameState::ServerGameState() : serverGameStage_(ServerGameStage::PRE_GAME) {}
|
||||||
|
|
||||||
void ServerGameState::init()
|
void ServerGameState::init()
|
||||||
{
|
{
|
||||||
deck_.clear(), discardPile_.clear();
|
|
||||||
while (discardPile_.isEmpty() || discardPile_.getFront().getType() > CardType::NUM9) {
|
while (discardPile_.isEmpty() || discardPile_.getFront().getType() > CardType::NUM9) {
|
||||||
discardPile_.add(deck_.draw());
|
discardPile_.add(deck_.draw());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &player : this->players_) {
|
|
||||||
while (player.isEmpty() == false) {
|
|
||||||
player.play(*player.getCards().begin());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < 7; i++) {
|
for (size_t i = 0; i < 7; i++) {
|
||||||
for (auto &player : this->players_) {
|
for (auto &player : this->players_) {
|
||||||
player.draw(1, this->deck_.draw(1));
|
player.draw(1, this->deck_.draw(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->serverGameStage_ = ServerGameStage::IN_GAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Card> ServerGameState::updateStateByDraw()
|
std::vector<Card> ServerGameState::updateStateByDraw()
|
||||||
@@ -151,18 +194,16 @@ namespace UNO::GAME {
|
|||||||
return cards;
|
return cards;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerGameState::reset()
|
ServerGameStage ServerGameState::getServerGameStage() const
|
||||||
{
|
{
|
||||||
discardPile_.clear();
|
return this->serverGameStage_;
|
||||||
isReversed_ = false;
|
}
|
||||||
drawCount_ = 0;
|
|
||||||
|
|
||||||
for (auto &player : players_) {
|
void ServerGameState::endGame()
|
||||||
while (!player.isEmpty()) {
|
{
|
||||||
player.play(*player.getCards().begin());
|
this->serverGameStage_ = ServerGameStage::PRE_GAME;
|
||||||
}
|
deck_.clear();
|
||||||
}
|
|
||||||
|
|
||||||
currentPlayer_ = players_.begin();
|
GameState::endGame();
|
||||||
}
|
}
|
||||||
} // namespace UNO::GAME
|
} // namespace UNO::GAME
|
||||||
@@ -60,6 +60,11 @@ namespace UNO::GAME {
|
|||||||
* 出一张牌
|
* 出一张牌
|
||||||
*/
|
*/
|
||||||
Card virtual play(const Card &card);
|
Card virtual play(const Card &card);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空手牌
|
||||||
|
*/
|
||||||
|
void virtual clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -112,6 +117,8 @@ namespace UNO::GAME {
|
|||||||
* @return 手牌是否为空
|
* @return 手牌是否为空
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] bool isEmpty() const;
|
[[nodiscard]] bool isEmpty() const;
|
||||||
|
|
||||||
|
void clear() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -142,7 +149,7 @@ namespace UNO::GAME {
|
|||||||
/**
|
/**
|
||||||
* 下一个玩家
|
* 下一个玩家
|
||||||
*/
|
*/
|
||||||
void nextPlayer();
|
void virtual nextPlayer();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~GameState() = default;
|
virtual ~GameState() = default;
|
||||||
@@ -189,6 +196,8 @@ namespace UNO::GAME {
|
|||||||
* 由于用户摸牌而改变状态
|
* 由于用户摸牌而改变状态
|
||||||
*/
|
*/
|
||||||
std::vector<Card> virtual updateStateByDraw();
|
std::vector<Card> virtual updateStateByDraw();
|
||||||
|
|
||||||
|
void virtual endGame();
|
||||||
};
|
};
|
||||||
|
|
||||||
template<PlayerStateTypeConcept PlayerStateType>
|
template<PlayerStateTypeConcept PlayerStateType>
|
||||||
@@ -300,9 +309,26 @@ namespace UNO::GAME {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<PlayerStateTypeConcept PlayerStateType>
|
||||||
|
void GameState<PlayerStateType>::endGame()
|
||||||
|
{
|
||||||
|
discardPile_.clear();
|
||||||
|
for (auto &player : this->players_) {
|
||||||
|
player.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum class ClientGameStage { PENDING_CONNECTION, PRE_GAME, ACTIVE, IDLE };
|
||||||
|
|
||||||
class ClientGameState final : public GameState<ClientPlayerState> {
|
class ClientGameState final : public GameState<ClientPlayerState> {
|
||||||
private:
|
private:
|
||||||
Player player_;
|
Player player_;
|
||||||
|
std::vector<ClientPlayerState>::const_iterator self_;
|
||||||
|
ClientGameStage clientGameStage_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void nextPlayer() override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ClientGameState(std::string name);
|
explicit ClientGameState(std::string name);
|
||||||
@@ -316,7 +342,11 @@ namespace UNO::GAME {
|
|||||||
/**
|
/**
|
||||||
* 初始化客户端状态
|
* 初始化客户端状态
|
||||||
*/
|
*/
|
||||||
void init(DiscardPile discardPile);
|
void init(const std::vector<ClientPlayerState> &players,
|
||||||
|
const DiscardPile &discardPile,
|
||||||
|
const std::multiset<Card> &handCard,
|
||||||
|
const size_t ¤tPlayerIndex,
|
||||||
|
const size_t &selfIndex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 摸一张牌
|
* 摸一张牌
|
||||||
@@ -340,11 +370,25 @@ namespace UNO::GAME {
|
|||||||
* @return 手牌是否为空
|
* @return 手牌是否为空
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] bool isEmpty() const;
|
[[nodiscard]] bool isEmpty() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取游戏阶段
|
||||||
|
* @return 游戏阶段
|
||||||
|
*/
|
||||||
|
[[nodiscard]] ClientGameStage getClientGameStage() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结束当前局
|
||||||
|
*/
|
||||||
|
void endGame() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class ServerGameStage { PRE_GAME, IN_GAME };
|
||||||
|
|
||||||
class ServerGameState final : public GameState<ServerPlayerState> {
|
class ServerGameState final : public GameState<ServerPlayerState> {
|
||||||
private:
|
private:
|
||||||
Deck deck_;
|
Deck deck_;
|
||||||
|
ServerGameStage serverGameStage_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ServerGameState();
|
ServerGameState();
|
||||||
@@ -360,9 +404,15 @@ namespace UNO::GAME {
|
|||||||
std::vector<Card> updateStateByDraw() override;
|
std::vector<Card> updateStateByDraw() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重置游戏状态(用于重新开始)
|
* 获取游戏阶段
|
||||||
|
* @return 游戏阶段
|
||||||
*/
|
*/
|
||||||
void reset();
|
[[nodiscard]] ServerGameStage getServerGameStage() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结束当前局
|
||||||
|
*/
|
||||||
|
void endGame() override;
|
||||||
};
|
};
|
||||||
} // namespace UNO::GAME
|
} // namespace UNO::GAME
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,11 @@ namespace UNO::GAME {
|
|||||||
return cards_.empty();
|
return cards_.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HandCard::clear()
|
||||||
|
{
|
||||||
|
this->cards_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
Player::Player(std::string name) : name_(std::move(name)) {}
|
Player::Player(std::string name) : name_(std::move(name)) {}
|
||||||
|
|
||||||
const std::string &Player::getName() const
|
const std::string &Player::getName() const
|
||||||
@@ -86,5 +91,8 @@ namespace UNO::GAME {
|
|||||||
return this->handCard_.play(card);
|
return this->handCard_.play(card);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Player::clear()
|
||||||
|
{
|
||||||
|
this->handCard_.clear();
|
||||||
}
|
}
|
||||||
} // namespace UNO::GAME
|
} // namespace UNO::GAME
|
||||||
|
|||||||
@@ -59,6 +59,11 @@ namespace UNO::GAME {
|
|||||||
* @return 手牌是否为空
|
* @return 手牌是否为空
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] bool isEmpty() const;
|
[[nodiscard]] bool isEmpty() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空手牌
|
||||||
|
*/
|
||||||
|
void clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -105,6 +110,11 @@ namespace UNO::GAME {
|
|||||||
* @return 手牌是否为空
|
* @return 手牌是否为空
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] bool isEmpty() const;
|
[[nodiscard]] bool isEmpty() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空手牌
|
||||||
|
*/
|
||||||
|
void clear();
|
||||||
};
|
};
|
||||||
} // namespace UNO::GAME
|
} // namespace UNO::GAME
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user