Fix after disconnect the change of parentID bug

This commit is contained in:
2025-12-07 12:06:40 +08:00
parent a6403953ef
commit a66c70f0b7
3 changed files with 143 additions and 19 deletions

View File

@@ -136,8 +136,24 @@ int Board::getComponentID(int row, int col) const{
} }
std::unordered_set<int> Board::getComponentByPieceID(int PieceID) const { std::unordered_set<int> Board::getComponentByPieceID(int PieceID) const {
std::cout << "DEBUG: getComponentByPieceID(" << PieceID << ")" << std::endl;
// 检查该位置是否有棋子
auto [row, col] = getCoordFromID(PieceID);
if (getPieceAt(row, col) == nullptr) {
std::cout << "this postion don't have piece\n";
return std::unordered_set<int>(); // 返回空集合
}
// 检查 ComponentManager 的状态
int componentID = m_component->getComponentID(PieceID);
std::cout << "DEBUG: componentID = " << componentID << std::endl;
// 临时选中组件
m_component->selectComponentByPiece(PieceID); m_component->selectComponentByPiece(PieceID);
auto SelectedComponent = m_component->getSelectedComponent(); auto SelectedComponent = m_component->getSelectedComponent();
// 立即清除选中状态
m_component->clearSelection();
std::cout << "DEBUG: Component size = " << SelectedComponent.size() << std::endl;
return SelectedComponent; return SelectedComponent;
} }

View File

@@ -1,5 +1,5 @@
#include "ComponentManager.h" #include "ComponentManager.h"
#include <iostream>
ComponentManager::ComponentManager(int maxPossiblePieces) ComponentManager::ComponentManager(int maxPossiblePieces)
: m_maxPossiblePieces(maxPossiblePieces) { : m_maxPossiblePieces(maxPossiblePieces) {
//初始化数组大小 ROWS * COLS //初始化数组大小 ROWS * COLS
@@ -30,15 +30,43 @@ void ComponentManager::addPiece(int PieceID, const std::vector<int>& adjacentPie
} }
void ComponentManager::removePiece(int PieceID) { void ComponentManager::removePiece(int PieceID) {
std::cout << "try to remove piece " << PieceID << " ";
// 先检查棋子是否存在
if (m_parent[PieceID] == -1){
std::cout << "piece don't extist" <<std::endl;
}
// 1. 断开所有连接(这会为棋子创建独立组件)
disconnectFromComponent(PieceID); disconnectFromComponent(PieceID);
/* // 2. 现在将棋子标记为不存在
m_parent[PieceID] = -1; m_parent[PieceID] = -1;
m_rank[PieceID] = 0;
// 3. 从组件映射中移除
m_pieceToComponent.erase(PieceID);
// 4. 从独立组件中移除
if (m_componentPieces.count(PieceID)) {
m_componentPieces.erase(PieceID);
}
//m_rank[PieceID] = 0; 重复设置了 //m_rank[PieceID] = 0; 重复设置了
//m_componentPieces.erase(PieceID); //m_componentPieces.erase(PieceID);
*/
} }
int ComponentManager::find(int pieceID) { int ComponentManager::find(int pieceID) {
std::cout << "DEBUG find: pieceID=" << pieceID;
// 添加边界检查
if (pieceID < 0 || pieceID >= m_maxPossiblePieces) {
std::cout << " -> Invalid range" << std::endl;
return -1; // 返回无效值
}
if (m_parent[pieceID] == -1) {
std::cout << " -> No parent (piece not exists)" << std::endl;
return -1; // 棋子不存在
}
if (m_parent[pieceID] != pieceID) { if (m_parent[pieceID] != pieceID) {
m_parent[pieceID] = find(m_parent[pieceID]); m_parent[pieceID] = find(m_parent[pieceID]);
} }
@@ -105,21 +133,55 @@ bool ComponentManager::disconnectFromComponent(int pieceID) {
for (int neighborID : neighbors) { for (int neighborID : neighbors) {
m_adjacentList[neighborID].erase(pieceID); m_adjacentList[neighborID].erase(pieceID);
} }
// 删除pieceID的邻接表 // 删除pieceID的邻接表
m_adjacentList[pieceID].clear(); m_adjacentList[pieceID].clear();
/* // 将被断开的棋子设为独立组件
m_parent[pieceID] = pieceID;
m_rank[pieceID] = 0;
m_componentPieces[pieceID] = {pieceID};
m_pieceToComponent[pieceID] = pieceID;
*/
// 从原组件中移除 pieceID // 从原组件中移除 pieceID
if (m_componentPieces.count(oldComponentID)) { if (m_componentPieces.count(oldComponentID)) {
// 1. 先从组件集合中移除这个棋子
m_componentPieces[oldComponentID].erase(pieceID); m_componentPieces[oldComponentID].erase(pieceID);
// 如果断开的是根节点这重新选择根节点
if (oldComponentID == pieceID) {
int newRoot = -1;
for (int remainingPiece : m_componentPieces[oldComponentID]) {
if (remainingPiece != pieceID) {
newRoot = remainingPiece;
break;
}
}
if (newRoot != -1) {
// 3. 如果找到新的根节点,更新组件映射
// 将原组件的数据迁移到新根节点
m_componentPieces[newRoot] = std::move(m_componentPieces[oldComponentID]);
m_componentPieces.erase(oldComponentID);
// 更新所有棋子的组件映射到新根节点
for (int piece : m_componentPieces[newRoot]) {
m_pieceToComponent[piece] = newRoot;
// 注意:这里不修改 m_parent因为会通过后续的重新计算来重建
}
oldComponentID = newRoot; // 更新oldRoot指向新的根节点
} else {
// 4. 如果没有其他棋子了,删除这个空组件
m_componentPieces.erase(oldComponentID);
}
} }
}
// 将被断开的棋子设为独立组件
//createNewComponent(pieceID);
// 删除这个组件
m_parent[pieceID] = -1;
m_pieceToComponent.erase(pieceID); m_pieceToComponent.erase(pieceID);
// 如果原组件还有其他棋子,需要重新计算连通性 // 如果原组件还有其他棋子,需要重新计算连通性
if (!m_componentPieces[oldComponentID].empty()) { if (!m_componentPieces[oldComponentID].empty()) {
recomputeComponentsAfterDisconnection(oldComponentID, m_componentPieces[oldComponentID]); recomputeComponentsAfterDisconnection(oldComponentID, m_componentPieces[oldComponentID]);
@@ -135,6 +197,14 @@ void ComponentManager::recomputeComponentsAfterDisconnection(int oldComponentID,
// 安全检查remainingPieces 至少要有 2 个棋子才可能分裂 // 安全检查remainingPieces 至少要有 2 个棋子才可能分裂
if (remainingPieces.size() <= 1) { if (remainingPieces.size() <= 1) {
int leftpieceID = *remainingPieces.begin();
// 将剩下的一个的棋子设为独立组件
createNewComponent(leftpieceID);
// 遍历那个棋子的邻接表
if (!m_adjacentList[leftpieceID].empty())
for (int neighbor : m_adjacentList[leftpieceID]) {
unite(leftpieceID, neighbor);
}
// 如果只剩 0 或 1 个棋子,不需要分裂 // 如果只剩 0 或 1 个棋子,不需要分裂
// (如果剩 1 个,它自己就是一个新组件;如果为 0调用方应已处理 // (如果剩 1 个,它自己就是一个新组件;如果为 0调用方应已处理
return; return;
@@ -160,7 +230,16 @@ void ComponentManager::handleComponentSplit(int oldComponentID, const std:: unor
// 标记为已访问 // 标记为已访问
visited.insert(connectedRegion.begin(), connectedRegion.end()); visited.insert(connectedRegion.begin(), connectedRegion.end());
newComponents.push_back(connectedRegion); // 确保区域中的棋子都是存在的parent != -1
std::unordered_set<int> validRegion;
for (int p : connectedRegion) {
if (m_parent[p] != -1) { // 只保留存在的棋子
validRegion.insert(p);
}
}
if (!validRegion.empty()) {
newComponents.push_back(validRegion);
}
} }
// 删除原组件 // 删除原组件
m_componentPieces.erase(oldComponentID); m_componentPieces.erase(oldComponentID);
@@ -168,14 +247,31 @@ void ComponentManager::handleComponentSplit(int oldComponentID, const std:: unor
// 为每个新连通区域创建组件 // 为每个新连通区域创建组件
for (const auto& region : newComponents) { for (const auto& region : newComponents) {
if (!region.empty()) { if (!region.empty()) {
int newRoot = *region.begin(); // 需要选择一个确实存在的棋子作为根
createNewComponent(newRoot); int newRoot = -1;
for (int piece : region) {
if (m_parent[piece] != -1) { // 找到第一个存在的棋子
newRoot = piece;
break;
}
}
if (newRoot == -1) continue; // 没有有效的棋子
// 确保根节点指向自己
m_parent[newRoot] = newRoot;
m_rank[newRoot] = 0;
// int newRoot = *region.begin();
// createNewComponent(newRoot);
// 设置新组件的父节点和棋子集合 // 设置新组件的父节点和棋子集合
for (int piece : region) { for (int piece : region) {
if (m_parent[piece] != -1) { // 只处理存在的棋子
m_parent[piece] = newRoot; m_parent[piece] = newRoot;
m_pieceToComponent[piece] = newRoot; m_pieceToComponent[piece] = newRoot;
} }
}
m_componentPieces[newRoot] = region; m_componentPieces[newRoot] = region;
} }
} }
@@ -185,6 +281,10 @@ void ComponentManager::handleComponentSplit(int oldComponentID, const std:: unor
std::unordered_set<int> ComponentManager::bfsConnectedRegion(int startPiece, const std::unordered_set<int>& availablepieces) { std::unordered_set<int> ComponentManager::bfsConnectedRegion(int startPiece, const std::unordered_set<int>& availablepieces) {
std::unordered_set<int> connectedRegion; std::unordered_set<int> connectedRegion;
// 如果起始棋子不存在,返回空区域
if (m_parent[startPiece] == -1) {
return connectedRegion;
}
std::queue<int> queue; std::queue<int> queue;
queue.push(startPiece); queue.push(startPiece);
@@ -218,6 +318,7 @@ int ComponentManager::createNewComponent(int rootPiece) {
void ComponentManager::selectComponentByPiece(int pieceID) { void ComponentManager::selectComponentByPiece(int pieceID) {
m_selectedComponentID = find(pieceID); m_selectedComponentID = find(pieceID);
std::cout << "DEBUG selectedComponentID is" << m_selectedComponentID << std::endl;
} }
const std::unordered_set<int>& ComponentManager::getSelectedComponent() const { const std::unordered_set<int>& ComponentManager::getSelectedComponent() const {
@@ -243,7 +344,12 @@ const std::unordered_set<int>& ComponentManager::getPiecesInComponent(int compon
} }
bool ComponentManager::areConnected(int pieceID1, int pieceID2) { bool ComponentManager::areConnected(int pieceID1, int pieceID2) {
return find(pieceID1) == find(pieceID2); int root1 = find(pieceID1);
int root2 = find(pieceID2);
if (root1 == -1 || root2 == -1) {
return false;
}
return root1 == root2;
} }
const std::unordered_set<int>& ComponentManager::getPieceConnections(int pieceID) const { const std::unordered_set<int>& ComponentManager::getPieceConnections(int pieceID) const {
@@ -261,6 +367,7 @@ bool ComponentManager::areDirectlyConnected(int pieceID1, int pieceID2) const {
} }
void ComponentManager::clearSelection() { void ComponentManager::clearSelection() {
std::cout << "DEBUG clear selected componentID is" << m_selectedComponentID << std::endl;
m_selectedComponentID = -1; m_selectedComponentID = -1;
} }

View File

@@ -29,7 +29,7 @@ bool Rule::canbeSelect(const Piece* PieceID, PlayerID ID) {
bool Rule::canGrow(const Board* board, const int fromRow, const int fromCol, const int toRow, const int toCol, const PlayerID player) { bool Rule::canGrow(const Board* board, const int fromRow, const int fromCol, const int toRow, const int toCol, const PlayerID player) {
std::cout << "try to grow\n";
// 检查是否有棋子并且属于自己 // 检查是否有棋子并且属于自己
const Piece* fromPiece = board->getPieceAt(fromRow, fromCol); const Piece* fromPiece = board->getPieceAt(fromRow, fromCol);
@@ -42,6 +42,7 @@ bool Rule::canGrow(const Board* board, const int fromRow, const int fromCol, con
if (board->getPieceAt(toRow, toCol) != nullptr) { if (board->getPieceAt(toRow, toCol) != nullptr) {
std::cout << "is exist a piece can't grow\n";
return false; // 有棋子不能生长 return false; // 有棋子不能生长
} }