Refined the core interfaces of the game

This commit is contained in:
2025-11-30 11:08:01 +08:00
parent 48728c1a5b
commit 532883835b
8 changed files with 138 additions and 32 deletions

View File

@@ -122,6 +122,10 @@ std::unordered_set<int> Board::getAllPlayerComponent(PlayerID ID) const {
return PlayerComponentIDs;
}
std::unordered_map<int, int> Board::getALLPiecetoComponent() const {
return m_component->getAllPiecetoComponent();
}
int Board::getComponentID(int row, int col) const{
int pieceID = getPieceID(row, col);
int componentID = m_component->getComponentID(pieceID);

View File

@@ -43,6 +43,8 @@ public:
void printBoard();
//获取相同玩家棋子的所有棋子块的根节点
std::unordered_set<int> getAllPlayerComponent(PlayerID ID) const;
//获取棋子ID到组件ID的映射
std::unordered_map<int, int> getALLPiecetoComponent() const;
// 获取坐标对应的块的ID
int getComponentID(int row, int col) const;
// 获取组件ID对应的组件

View File

@@ -269,6 +269,10 @@ std:: unordered_map<int, std::unordered_set<int>> ComponentManager::getAllCompon
}
std::unordered_map<int, int> ComponentManager::getAllPiecetoComponent() const {
return m_pieceToComponent;
}

View File

@@ -47,7 +47,7 @@ public:
// 连接两个组件
void addConnection(int pieceID1, int pieceID2);
// 断开棋子与指定邻居的连接
bool disconnectFromNeighbor(int pieceID, int neighborID);
//bool disconnectFromNeighbor(int pieceID, int neighborID);
// 将棋子完全从当前组件断开,成为独立组件
bool disconnectFromComponent(int pieceID);
// 通过棋子选择整个连通片
@@ -66,9 +66,10 @@ public:
bool areDirectlyConnected(int pieceID1, int pieceID2) const;
// 清除选中状态
void clearSelection();
// 不能返回引用因为要保存旧的组件
//获取所有组件
std::unordered_map<int, std::unordered_set<int>> getAllComponents() const;
//获取棋子ID到组件ID的映射
std::unordered_map<int, int> getAllPiecetoComponent() const;
};

View File

@@ -24,8 +24,8 @@ bool Game::initialize() {
return false;
}
m_board->printBoard();
resetActionableComponents();
resetOldPieceIDtoComponent();
@@ -38,15 +38,8 @@ void Game::resetActionableComponents() {
m_actionableComponents = m_board->getAllPlayerComponent(m_currentPlayer);
}
bool Game::playerSelectPiece(int row, int col) {
if (Rule::canbeSelect(m_board->getPieceAt(row, col), m_currentPlayer)) {
/*if (m_seletedPiece == std::nullopt) {
m_seletedPiece = {row, col};
}*/
m_seletedPiece = {row, col};
}
return true;
void Game::resetOldPieceIDtoComponent() {
m_oldPieceIDtoComponentID = m_board->getALLPiecetoComponent();
}
void Game::setPlayerAction(ActionType type) {
@@ -60,7 +53,7 @@ void Game::executeAction(int toRow, int toCol) {
if (Rule::canGrow(m_board.get(), fromRow, fromCol, toRow, toCol, m_currentPlayer)) {
m_board->placePieceAt(toRow, toCol, m_currentPlayer);
// 如果执行了操作就擦除
markComponentAsUsed(m_board->getComponentID(fromRow, fromCol));
markComponentAsUsed(getOldComponentID(fromRow, fromCol));
return;
}
}
@@ -70,7 +63,7 @@ void Game::executeAction(int toRow, int toCol) {
m_board->removePieceAt(toRow, toCol);
m_board->placePieceAt(toRow, toCol, m_currentPlayer);
markComponentAsUsed(m_board->getComponentID(fromRow, fromCol));
markComponentAsUsed(getOldComponentID(fromRow, fromCol));
return;
}
}
@@ -79,7 +72,7 @@ void Game::executeAction(int toRow, int toCol) {
m_board->removePieceAt(fromRow, fromCol);
m_board->placePieceAt(toRow, toCol, m_currentPlayer);
markComponentAsUsed(m_board->getComponentID(fromRow, fromCol));
markComponentAsUsed(getOldComponentID(fromRow, fromCol));
return;
}
}
@@ -87,7 +80,13 @@ void Game::executeAction(int toRow, int toCol) {
}
void Game::markComponentAsUsed(int componentID) {
m_actionableComponents.erase(componentID);
std::cout << "try erase the componentID is " << componentID <<"\n";
int num = m_actionableComponents.erase(componentID);
if (num == 1) {
std::cout << "erase successful\n";
} else {
std::cout << "erase error\n";
}
}
PlayerID Game::getCurrentPlayer() const {
@@ -97,3 +96,94 @@ PlayerID Game::getCurrentPlayer() const {
void Game::printBoard() const {
m_board->printBoard();
}
void Game::nextTurn() {
std::cout << "switch to P2\n";
m_seletedPiece = std::nullopt;
m_currentPlayer = (m_currentPlayer == PlayerID::P1) ? PlayerID::P2 : PlayerID::P1;
resetOldPieceIDtoComponent();
resetActionableComponents();
m_currentActionType = ActionType::GROW;
}
bool Game::handleCoordinateInput(int row, int col) {
// 如果当前没有选择棋子就选择棋子
if (m_seletedPiece == std::nullopt) {
if (!Rule::canbeSelect(m_board->getPieceAt(row, col), m_currentPlayer)) {
std::cout << "sorry you can't select the piece\n";
return false;
}
m_seletedPiece = {row, col};
std::cout << "selcte piece successful\n";
return true;
}
std::cout << "selectedpiece is " << m_seletedPiece->first << " " << m_seletedPiece->second << "\n";
// 如果点击了选择的棋子就切换行动方式
std::pair<int ,int> newSelectedPiece = {row, col};
if (m_seletedPiece == newSelectedPiece) {
switch (m_currentActionType)
{
case ActionType::GROW:
m_currentActionType = ActionType::MOVE;
std::cout << "switch actiontype to MOVE successful\n";
break;
case ActionType::MOVE:
m_currentActionType = ActionType::SPORE;
std::cout << "switch actiontype to SPORE successful\n";
break;
case ActionType::SPORE:
m_currentActionType = ActionType::GROW;
std::cout << "switch actiontype to GROW successful\n";
break;
default:
std::cout << "switch actiontype wrong\n";
return false;
}
return true;
}
//如果点击了属于当前玩家且没有行动的的其它棋子,就切换选择棋子到其它棋子
int selectComponentID = getOldComponentID(row, col);
if (m_actionableComponents.find(selectComponentID) != m_actionableComponents.end()) {
m_seletedPiece = newSelectedPiece;
std::cout << "switch the selectedpiece to " << m_seletedPiece->first << " " << m_seletedPiece->second << "\n";
return true;
}
// 如果点击了已经行动的棋子,则不进行处理,已行动的棋子如果是在一个单独的区域不用处理,但如果是在一个未行动的组件中欧是可以再次行动的,
//但是如果点击同一块 也无需处理,因为 在m_actionableComponents已经不存在了直接尝试执行行动但因为rule处理了所以不用管
// 其它情况则执行行动
executeAction(row, col);
// 执行完之后检查是否m_actionableComponents为空
// m_actionableComponents只保存了ID但是在执行棋子之后会处理组件的连通性rule会获取到新的连通性不过这样更符合逻辑
//如果不是空的这默认将m_seletedPiece切换到这个组件之中
//如果是空的则进行下一轮切换玩家
if (m_actionableComponents.empty()) {
nextTurn();
return true;
} else {
for (auto leftcomponentID : m_actionableComponents) {
std::cout << "leftcomponentID is " << leftcomponentID << "\n";
}
auto leftcomponent = m_actionableComponents.begin();
m_seletedPiece = m_board->getCoordFromID(*leftcomponent);
std::cout << "switch the selectedpiece to " << m_seletedPiece->first << " " << m_seletedPiece->second << "\n";
return true;
}
}
int Game::getOldComponentID(int row, int col) {
int pieceID = m_board->getPieceID(row, col);
auto it = m_oldPieceIDtoComponentID.find(pieceID);
//for (auto [pieceID, y] : m_oldPieceIDtoComponentID)
return (it != m_oldPieceIDtoComponentID.end()) ? it->second : -1;
}

View File

@@ -14,10 +14,13 @@ private:
std::unique_ptr<Board> m_board;
PlayerID m_currentPlayer = PlayerID::P1;
ActionType m_currentActionType = ActionType::GROW;
std::optional<std::pair<int, int>> m_seletedPiece; //表示“可能有值,也可能没有值”
std::optional<std::pair<int, int>> m_seletedPiece = std::nullopt; //表示“可能有值,也可能没有值”
std::unordered_set<int> m_actionableComponents;;
// 保存旧的componentid与pieceid的对应关系
std::unordered_map<int, int> m_oldPieceIDtoComponentID;
// 如果操作执行成功就从
void markComponentAsUsed(int componentID);
public:
Game();
@@ -26,8 +29,8 @@ public:
bool initialize();
//获取当前玩家的拥有的组件
void resetActionableComponents();
// 获取用户选择的棋子
bool playerSelectPiece(int row, int col);
//旧的componentid与pieceid的对应关系
void resetOldPieceIDtoComponent();
// 设置行动类型
void setPlayerAction(ActionType type);
// 执行玩家的行动
@@ -36,4 +39,13 @@ public:
PlayerID getCurrentPlayer() const;
// 打印棋盘
void printBoard() const;
// 下一个轮次
void nextTurn();
// 根据当前状态自动处理坐标输入:
// - 如果尚未选中棋子 → 尝试选中
// - 如果已选中棋子 → 尝试执行当前动作类型GROW/MOVE/SPORE
bool handleCoordinateInput(int row, int col);
int getOldComponentID(int row, int col);
};

View File

@@ -21,7 +21,7 @@ bool Rule::canPlacePiece(const Piece* piecePos) {
}
bool Rule::canbeSelect(const Piece* PieceID, PlayerID ID) {
if (PieceID->getPieceOwner() != ID) {
if (PieceID == nullptr || PieceID->getPieceOwner() != ID) {
return false;
}
return true;

View File

@@ -13,19 +13,12 @@ int main() {
while (true) {
std::cout << "Current player: "
<< (game.getCurrentPlayer() == PlayerID::P1 ? "P1" : "P2") << "\n";
std::cout << "Action type (0=GROW, 1=MOVE, 2=SPORE): ";
int act;
std::cin >> act;
game.setPlayerAction(static_cast<ActionType>(act));
std::cout << "Select piece (row col): ";
std::cout << "input piece (row col): ";
int r, c;
std::cin >> r >> c;
game.playerSelectPiece(r, c);
std::cout << "Target position (row col): ";
std::cin >> r >> c;
game.executeAction(r, c);
game.handleCoordinateInput(r, c);
game.printBoard();
}