From c6a0f3b73586c58d02cb36e23af2ecff05ac0002 Mon Sep 17 00:00:00 2001 From: zhenyan121 <3367366583@qq.com> Date: Thu, 27 Nov 2025 21:24:10 +0800 Subject: [PATCH] Add place piece function --- src/core/Board.cpp | 33 ++++++-- src/core/Board.h | 4 + src/core/ComponentManager.cpp | 143 +++++++++++++++++++--------------- src/core/ComponentManager.h | 32 ++++---- src/core/GameTypes.h | 6 ++ src/core/Piece.h | 6 +- src/core/Rule.cpp | 10 +++ src/core/Rule.h | 11 ++- 8 files changed, 155 insertions(+), 90 deletions(-) create mode 100644 src/core/GameTypes.h diff --git a/src/core/Board.cpp b/src/core/Board.cpp index 283f1c4..5ef0653 100644 --- a/src/core/Board.cpp +++ b/src/core/Board.cpp @@ -11,16 +11,39 @@ Board::Board(int rows, int cols) : Board::~Board() { } - +//将二维坐标转化成一维坐标 const int Board::getIndex(int row, int col) { return row * m_cols + col; } +void Board::placePieceAt(int row, int col, PlayerID ID) { + int index = getIndex(row, col); + m_grid[index] = std::make_unique(ID); + //创建方向数组 + const int dx[] = {0, 0, -1, 1}; + const int dy[] = {-1, 1, 0, 0}; + std::vector existingNeighbors; //记录附近的同色邻居 + + for (int i = 0; i < 4; i++) { + int nx = row + dx[i]; + int ny = col + dy[i]; + int pos = getIndex(nx, ny); + //添加邻居 + if (m_grid[pos] != nullptr && Rule::canConnect(m_grid[index]->getPieceOwner(), m_grid[pos]->getPieceOwner())) { + existingNeighbors.push_back(pos); + + } + } + // 调用componet处理一片的添加和连接操作 + m_component->addPiece(index, existingNeighbors); + +} + bool Board::initialize() { - m_grid[getIndex(0, 0)] = std::make_unique(PlayerID::P1); - m_grid[getIndex(0, 2)] = std::make_unique(PlayerID::P1); - m_grid[getIndex(6, 6)] = std::make_unique(PlayerID::P2); - m_grid[getIndex(5, 5)] = std::make_unique(PlayerID::P2); + placePieceAt(0, 0, PlayerID::P1); + placePieceAt(0 ,2, PlayerID::P1); + placePieceAt(6, 6, PlayerID::P2); + placePieceAt(5, 5, PlayerID::P2); } diff --git a/src/core/Board.h b/src/core/Board.h index 46ddad9..8458cdf 100644 --- a/src/core/Board.h +++ b/src/core/Board.h @@ -1,6 +1,7 @@ #pragma once #include "Piece.h" #include "ComponentManager.h" +#include "Rule.h" #include #include // 用 (row, col) 表示坐标,0-based @@ -17,6 +18,7 @@ class Board { private: //使用一维数组表示棋盘 std::vector> m_grid; + // 连接片管理 std::unique_ptr m_component; const int m_rows; const int m_cols; @@ -26,4 +28,6 @@ public: const int getIndex(int row, int col); std::unique_ptr& at(int row, int col); bool initialize(); + // 放置棋子 + void placePieceAt(int row, int col, PlayerID ID); }; \ No newline at end of file diff --git a/src/core/ComponentManager.cpp b/src/core/ComponentManager.cpp index 7fbc99c..2c605ae 100644 --- a/src/core/ComponentManager.cpp +++ b/src/core/ComponentManager.cpp @@ -1,29 +1,44 @@ #include "ComponentManager.h" -ComponentManager::ComponentManager(int numPieces) - : m_totalPieces(numPieces) { +ComponentManager::ComponentManager(int maxPossiblePieces) + : m_maxPossiblePieces(maxPossiblePieces) { //初始化数组大小 ROWS * COLS - m_parent.resize(numPieces); - m_rank.resize(numPieces, 0); - m_adjacentList.resize(numPieces); - //初始化每个棋子为独立组件 - for (int i = 0; i < numPieces; i++) { - m_parent[i] = i; - m_componentPieces[i] = {i}; //每个组件初始包含一个棋子 - m_pieceToComponent[i] = i; //棋子指向的组件 - } + m_parent.resize(maxPossiblePieces, -1); // -1表示无棋子 + m_rank.resize(maxPossiblePieces, 0); + m_adjacentList.resize(maxPossiblePieces); + } -int ComponentManager::find(int pieceId) { - if (m_parent[pieceId] != pieceId) { - m_parent[pieceId] = find(m_parent[pieceId]); +void ComponentManager::addPiece(int PieceID, const std::vector& adjacentPiece) { + if (PieceID < 0 || PieceID >= m_maxPossiblePieces) return; + if (m_parent[PieceID] == -1) return; // 已存在 + + m_parent[PieceID] = PieceID; + m_rank[PieceID] = PieceID; + m_componentPieces[PieceID] = {PieceID}; + m_pieceToComponent[PieceID] = PieceID; + + for (int neighbor : adjacentPiece) { + if (neighbor < 0 || neighbor >= m_maxPossiblePieces || m_parent[neighbor] == -1) + continue; // 邻居无效或不存在 + // 合并连通组件(unite 会自动处理是否已在同一组件) + unite(PieceID, neighbor); + + addConnection(PieceID, neighbor); } - return m_parent[pieceId]; + } -void ComponentManager::unite(int pieceId1, int pieceId2) { - int root1 = find(pieceId1); - int root2 = find(pieceId2); +int ComponentManager::find(int pieceID) { + if (m_parent[pieceID] != pieceID) { + m_parent[pieceID] = find(m_parent[pieceID]); + } + return m_parent[pieceID]; +} + +void ComponentManager::unite(int pieceID1, int pieceID2) { + int root1 = find(pieceID1); + int root2 = find(pieceID2); if (root1 == root2) { return; @@ -46,71 +61,71 @@ void ComponentManager::unite(int pieceId1, int pieceId2) { m_pieceToComponent[piece] = root1; } } - addConnection(pieceId1, pieceId2); + addConnection(pieceID1, pieceID2); } -void ComponentManager::addConnection(int pieceId1, int pieceId2) { +void ComponentManager::addConnection(int pieceID1, int pieceID2) { //将元素放入邻接表 - m_adjacentList[pieceId1].insert(pieceId2); - m_adjacentList[pieceId2].insert(pieceId1); + m_adjacentList[pieceID1].insert(pieceID2); + m_adjacentList[pieceID2].insert(pieceID1); } -bool ComponentManager::disconnectFromNeighbor(int pieceId, int neighborId){ +bool ComponentManager::disconnectFromNeighbor(int pieceID, int neighborID){ // 检查是否真的相连 - if (!areDirectlyConnected(pieceId, neighborId)) { + if (!areDirectlyConnected(pieceID, neighborID)) { return false; } // 从邻接表中移除连接 - m_adjacentList[pieceId].erase(neighborId); - m_adjacentList[neighborId].erase(pieceId); + m_adjacentList[pieceID].erase(neighborID); + m_adjacentList[neighborID].erase(pieceID); // 重新计算连通性 - recomputeComponentsAfterDisconnection(pieceId); + recomputeComponentsAfterDisconnection(pieceID); return true; } -bool ComponentManager::disconnectFromComponent(int pieceId) { - int oldComponentId = find(pieceId); - if (oldComponentId == -1) return false; +bool ComponentManager::disconnectFromComponent(int pieceID) { + int oldComponentID = find(pieceID); + if (oldComponentID == -1) return false; // 记录所有直接连接 - auto neighbors = m_adjacentList[pieceId]; + auto neighbors = m_adjacentList[pieceID]; // 断开所有连接 - for (int neighborId : neighbors) { - m_adjacentList[pieceId].erase(neighborId); - m_adjacentList[neighborId].erase(pieceId); + for (int neighborID : neighbors) { + m_adjacentList[pieceID].erase(neighborID); + m_adjacentList[neighborID].erase(pieceID); } // 将被断开的棋子设为独立组件 - m_parent[pieceId] = pieceId; - m_rank[pieceId] = 0; - m_componentPieces[pieceId] = {pieceId}; - m_pieceToComponent[pieceId] = pieceId; + m_parent[pieceID] = pieceID; + m_rank[pieceID] = 0; + m_componentPieces[pieceID] = {pieceID}; + m_pieceToComponent[pieceID] = pieceID; // 如果原组件还有其他棋子,需要重新计算连通性 if (!neighbors.empty()) { - recomputeComponentsAfterDisconnection(pieceId); + recomputeComponentsAfterDisconnection(pieceID); } return true; } void ComponentManager::recomputeComponentsAfterDisconnection(int disconnectedPiece) { - int oldComponentId = find(disconnectedPiece); - if (oldComponentId == -1 || m_componentPieces[disconnectedPiece].size() <= 1) { + int oldComponentID = find(disconnectedPiece); + if (oldComponentID == -1 || m_componentPieces[disconnectedPiece].size() <= 1) { return; } // 获取原组件中除断开棋子外的所有棋子 - std::unordered_set remainingPieces = m_componentPieces[oldComponentId]; + std::unordered_set remainingPieces = m_componentPieces[oldComponentID]; remainingPieces.erase(disconnectedPiece); //处理组件分裂 - handleComponentSplit(oldComponentId, remainingPieces); + handleComponentSplit(oldComponentID, remainingPieces); } -void ComponentManager::handleComponentSplit(int oldComponentId, const std:: unordered_set& remainingPieces ) { +void ComponentManager::handleComponentSplit(int oldComponentID, const std:: unordered_set& remainingPieces ) { std::unordered_set visited; std::vector> newComponents; @@ -128,7 +143,7 @@ void ComponentManager::handleComponentSplit(int oldComponentId, const std:: unor newComponents.push_back(connectedRegion); } // 删除原组件 - m_componentPieces.erase(oldComponentId); + m_componentPieces.erase(oldComponentID); // 为每个新连通区域创建组件 for (const auto& region : newComponents) { @@ -181,52 +196,52 @@ int ComponentManager::createNewComponent(int rootPiece) { return rootPiece; } -void ComponentManager::selectComponentByPiece(int pieceId) { - m_selectedComponentId = find(pieceId); +void ComponentManager::selectComponentByPiece(int pieceID) { + m_selectedComponentID = find(pieceID); } const std::unordered_set& ComponentManager::getSelectedComponent() const { static std::unordered_set emptySet; - if (m_selectedComponentId == -1 || - m_componentPieces.find(m_selectedComponentId) == m_componentPieces.end()) { + if (m_selectedComponentID == -1 || + m_componentPieces.find(m_selectedComponentID) == m_componentPieces.end()) { return emptySet; } - return m_componentPieces.at(m_selectedComponentId); + return m_componentPieces.at(m_selectedComponentID); } -int ComponentManager::getComponentId(int pieceId) const { - auto it = m_pieceToComponent.find(pieceId); +int ComponentManager::getComponentID(int pieceID) const { + auto it = m_pieceToComponent.find(pieceID); return (it != m_pieceToComponent.end()) ? it->second : -1; } -const std::unordered_set& ComponentManager::getPiecesInComponent(int componentId) const { +const std::unordered_set& ComponentManager::getPiecesInComponent(int componentID) const { static std::unordered_set emptySet; - auto it = m_componentPieces.find(componentId); + auto it = m_componentPieces.find(componentID); return (it != m_componentPieces.end()) ? it->second : emptySet; } -bool ComponentManager::areConnected(int pieceId1, int pieceId2) { - return find(pieceId1) == find(pieceId2); +bool ComponentManager::areConnected(int pieceID1, int pieceID2) { + return find(pieceID1) == find(pieceID2); } -const std::unordered_set& ComponentManager::getPieceConnections(int pieceId) const { +const std::unordered_set& ComponentManager::getPieceConnections(int pieceID) const { static std::unordered_set emptySet; - if (pieceId < 0 || pieceId >= m_totalPieces) return emptySet; - return m_adjacentList[pieceId]; + if (pieceID < 0 || pieceID >= m_maxPossiblePieces) return emptySet; + return m_adjacentList[pieceID]; } -bool ComponentManager::areDirectlyConnected(int pieceId1, int pieceId2) const { - if (pieceId1 < 0 || pieceId1 >= m_totalPieces || - pieceId2 < 0 || pieceId2 >= m_totalPieces) { +bool ComponentManager::areDirectlyConnected(int pieceID1, int pieceID2) const { + if (pieceID1 < 0 || pieceID1 >= m_maxPossiblePieces || + pieceID2 < 0 || pieceID2 >= m_maxPossiblePieces) { return false; } - return m_adjacentList[pieceId1].find(pieceId2) != m_adjacentList[pieceId1].end(); + return m_adjacentList[pieceID1].find(pieceID2) != m_adjacentList[pieceID1].end(); } void ComponentManager::clearSelection() { - m_selectedComponentId = -1; + m_selectedComponentID = -1; } std:: unordered_map> ComponentManager::getAllComponents() const { diff --git a/src/core/ComponentManager.h b/src/core/ComponentManager.h index 26d6e6c..d3af0eb 100644 --- a/src/core/ComponentManager.h +++ b/src/core/ComponentManager.h @@ -18,14 +18,14 @@ private: // 棋子ID到组件ID的映射 std::unordered_map m_pieceToComponent; // 当前选中的组件ID - int m_selectedComponentId = -1; + int m_selectedComponentID = -1; // 总棋子数 - int m_totalPieces; + int m_maxPossiblePieces; // 重新计算连通性(断开后调用) void recomputeComponentsAfterDisconnection(int disconnectedPiece); // 处理组件分裂 - void handleComponentSplit(int oldComponentId, const std::unordered_set& affectedPieces); + void handleComponentSplit(int oldComponentID, const std::unordered_set& affectedPieces); // 使用BFS查找连通区域 std::unordered_set bfsConnectedRegion(int startPiece, const std::unordered_set& afftedPieces); @@ -35,31 +35,33 @@ private: public: // 构造函数:初始化指定数量的棋子 - explicit ComponentManager(int numPieces); + explicit ComponentManager(int maxPossiblePieces); + //添加棋子 + void addPiece(int PieceID, const std::vector& adjacentPiece); // 查找操作(带路径压缩) - int find(int pieceId); + int find(int pieceID); // 合并两个棋子所在的组件(按秩合并) - void unite(int pieceId1, int pieceId2); + void unite(int pieceID1, int pieceID2); // 连接两个组件 - void addConnection(int pieceId1, int pieceId2); + void addConnection(int pieceID1, int pieceID2); // 断开棋子与指定邻居的连接 - bool disconnectFromNeighbor(int pieceId, int neighborId); + bool disconnectFromNeighbor(int pieceID, int neighborID); // 将棋子完全从当前组件断开,成为独立组件 - bool disconnectFromComponent(int pieceId); + bool disconnectFromComponent(int pieceID); // 通过棋子选择整个连通片 - void selectComponentByPiece(int pieceId); + void selectComponentByPiece(int pieceID); // 获取当前选中的组件中的所有棋子 const std::unordered_set& getSelectedComponent() const; // 获取棋子所属的组件ID - int getComponentId(int pieceId) const; + int getComponentID(int pieceID) const; // 获取组件内所有棋子 - const std::unordered_set& getPiecesInComponent(int pieceId) const; + const std::unordered_set& getPiecesInComponent(int pieceID) const; // 检查两个棋子是否在同一个组件中 - bool areConnected(int pieceId1, int pieceId2); + bool areConnected(int pieceID1, int pieceID2); // 获取棋子的所有直接连接 - const std::unordered_set& getPieceConnections(int pieceId) const; + const std::unordered_set& getPieceConnections(int pieceID) const; // 检查两个棋子是否直接相连 - bool areDirectlyConnected(int pieceId1, int pieceId2) const; + bool areDirectlyConnected(int pieceID1, int pieceID2) const; // 清除选中状态 void clearSelection(); diff --git a/src/core/GameTypes.h b/src/core/GameTypes.h new file mode 100644 index 0000000..1915ccc --- /dev/null +++ b/src/core/GameTypes.h @@ -0,0 +1,6 @@ +#pragma once +// 这里存储游戏的各种状态 +enum class PlayerID { + P1, + P2 +}; diff --git a/src/core/Piece.h b/src/core/Piece.h index a086ba0..faa0d6a 100644 --- a/src/core/Piece.h +++ b/src/core/Piece.h @@ -1,9 +1,5 @@ #pragma once - -enum class PlayerID { - P1, - P2 -}; +#include "GameTypes.h" class Piece { diff --git a/src/core/Rule.cpp b/src/core/Rule.cpp index e69de29..6929121 100644 --- a/src/core/Rule.cpp +++ b/src/core/Rule.cpp @@ -0,0 +1,10 @@ +#include "Rule.h" + + +bool Rule::canConnect(const PlayerID a, const PlayerID b) { + if (a == b) { + return true; + } + return false; + +} \ No newline at end of file diff --git a/src/core/Rule.h b/src/core/Rule.h index 7b9637e..a249d71 100644 --- a/src/core/Rule.h +++ b/src/core/Rule.h @@ -1 +1,10 @@ -#pragma once \ No newline at end of file +#pragma once +#include "GameTypes.h" + + + +class Rule { +public: + static bool canConnect(const PlayerID a, PlayerID b); + +}; \ No newline at end of file