mirror of
https://github.com/zhenyan121/SporeBG-Conid.git
synced 2026-04-10 06:14:08 +08:00
Fix after disconnect the change of parentID bug
This commit is contained in:
@@ -136,8 +136,24 @@ int Board::getComponentID(int row, int col) 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);
|
||||
auto SelectedComponent = m_component->getSelectedComponent();
|
||||
|
||||
// 立即清除选中状态
|
||||
m_component->clearSelection();
|
||||
std::cout << "DEBUG: Component size = " << SelectedComponent.size() << std::endl;
|
||||
return SelectedComponent;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "ComponentManager.h"
|
||||
|
||||
#include <iostream>
|
||||
ComponentManager::ComponentManager(int maxPossiblePieces)
|
||||
: m_maxPossiblePieces(maxPossiblePieces) {
|
||||
//初始化数组大小 ROWS * COLS
|
||||
@@ -30,15 +30,43 @@ void ComponentManager::addPiece(int PieceID, const std::vector<int>& adjacentPie
|
||||
}
|
||||
|
||||
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);
|
||||
/* // 2. 现在将棋子标记为不存在
|
||||
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_componentPieces.erase(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) {
|
||||
m_parent[pieceID] = find(m_parent[pieceID]);
|
||||
}
|
||||
@@ -105,21 +133,55 @@ bool ComponentManager::disconnectFromComponent(int pieceID) {
|
||||
for (int neighborID : neighbors) {
|
||||
|
||||
m_adjacentList[neighborID].erase(pieceID);
|
||||
|
||||
}
|
||||
// 删除pieceID的邻接表
|
||||
m_adjacentList[pieceID].clear();
|
||||
/* // 将被断开的棋子设为独立组件
|
||||
m_parent[pieceID] = pieceID;
|
||||
m_rank[pieceID] = 0;
|
||||
m_componentPieces[pieceID] = {pieceID};
|
||||
m_pieceToComponent[pieceID] = pieceID;
|
||||
*/
|
||||
// 从原组件中移除 pieceID
|
||||
if (m_componentPieces.count(oldComponentID)) {
|
||||
m_componentPieces[oldComponentID].erase(pieceID);
|
||||
}
|
||||
|
||||
|
||||
// 从原组件中移除 pieceID
|
||||
|
||||
if (m_componentPieces.count(oldComponentID)) {
|
||||
// 1. 先从组件集合中移除这个棋子
|
||||
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);
|
||||
|
||||
|
||||
|
||||
// 如果原组件还有其他棋子,需要重新计算连通性
|
||||
if (!m_componentPieces[oldComponentID].empty()) {
|
||||
recomputeComponentsAfterDisconnection(oldComponentID, m_componentPieces[oldComponentID]);
|
||||
@@ -135,6 +197,14 @@ void ComponentManager::recomputeComponentsAfterDisconnection(int oldComponentID,
|
||||
|
||||
// 安全检查:remainingPieces 至少要有 2 个棋子才可能分裂
|
||||
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 个棋子,不需要分裂
|
||||
// (如果剩 1 个,它自己就是一个新组件;如果为 0,调用方应已处理)
|
||||
return;
|
||||
@@ -160,7 +230,16 @@ void ComponentManager::handleComponentSplit(int oldComponentID, const std:: unor
|
||||
|
||||
// 标记为已访问
|
||||
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);
|
||||
@@ -168,13 +247,30 @@ void ComponentManager::handleComponentSplit(int oldComponentID, const std:: unor
|
||||
// 为每个新连通区域创建组件
|
||||
for (const auto& region : newComponents) {
|
||||
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) {
|
||||
m_parent[piece] = newRoot;
|
||||
m_pieceToComponent[piece] = newRoot;
|
||||
if (m_parent[piece] != -1) { // 只处理存在的棋子
|
||||
m_parent[piece] = newRoot;
|
||||
m_pieceToComponent[piece] = newRoot;
|
||||
}
|
||||
}
|
||||
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> connectedRegion;
|
||||
// 如果起始棋子不存在,返回空区域
|
||||
if (m_parent[startPiece] == -1) {
|
||||
return connectedRegion;
|
||||
}
|
||||
std::queue<int> queue;
|
||||
|
||||
queue.push(startPiece);
|
||||
@@ -218,6 +318,7 @@ int ComponentManager::createNewComponent(int rootPiece) {
|
||||
|
||||
void ComponentManager::selectComponentByPiece(int pieceID) {
|
||||
m_selectedComponentID = find(pieceID);
|
||||
std::cout << "DEBUG selectedComponentID is" << m_selectedComponentID << std::endl;
|
||||
}
|
||||
|
||||
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) {
|
||||
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 {
|
||||
@@ -261,6 +367,7 @@ bool ComponentManager::areDirectlyConnected(int pieceID1, int pieceID2) const {
|
||||
}
|
||||
|
||||
void ComponentManager::clearSelection() {
|
||||
std::cout << "DEBUG clear selected componentID is" << m_selectedComponentID << std::endl;
|
||||
m_selectedComponentID = -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
|
||||
std::cout << "try to grow\n";
|
||||
|
||||
// 检查是否有棋子并且属于自己
|
||||
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) {
|
||||
std::cout << "is exist a piece can't grow\n";
|
||||
return false; // 有棋子不能生长
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user