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::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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
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);
|
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,13 +247,30 @@ 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) {
|
||||||
m_parent[piece] = newRoot;
|
if (m_parent[piece] != -1) { // 只处理存在的棋子
|
||||||
m_pieceToComponent[piece] = newRoot;
|
m_parent[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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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; // 有棋子不能生长
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user