新增专心拼豆模式及相关弹窗,优化用户交互体验,提升功能可用性。

This commit is contained in:
zihanjian
2025-06-06 18:54:00 +08:00
parent 2577294390
commit 2e42ba01b8
10 changed files with 1543 additions and 3 deletions

145
src/utils/floodFillUtils.ts Normal file
View File

@@ -0,0 +1,145 @@
import { MappedPixel } from './pixelation';
// 洪水填充获取连通区域
export function getConnectedRegion(
mappedPixelData: MappedPixel[][],
startRow: number,
startCol: number,
targetColor: string
): { row: number; col: number }[] {
if (!mappedPixelData || !mappedPixelData[startRow] || !mappedPixelData[startRow][startCol]) {
return [];
}
const M = mappedPixelData.length;
const N = mappedPixelData[0].length;
const visited = Array(M).fill(null).map(() => Array(N).fill(false));
const region: { row: number; col: number }[] = [];
// 使用栈实现非递归洪水填充
const stack = [{ row: startRow, col: startCol }];
while (stack.length > 0) {
const { row, col } = stack.pop()!;
// 检查边界
if (row < 0 || row >= M || col < 0 || col >= N || visited[row][col]) {
continue;
}
const currentCell = mappedPixelData[row][col];
// 检查是否是目标颜色且不是外部区域
if (!currentCell || currentCell.isExternal || currentCell.color !== targetColor) {
continue;
}
// 标记为已访问
visited[row][col] = true;
// 添加到区域
region.push({ row, col });
// 添加相邻像素到栈中
stack.push(
{ row: row - 1, col }, // 上
{ row: row + 1, col }, // 下
{ row, col: col - 1 }, // 左
{ row, col: col + 1 } // 右
);
}
return region;
}
// 获取所有同颜色的连通区域
export function getAllConnectedRegions(
mappedPixelData: MappedPixel[][],
targetColor: string
): { row: number; col: number }[][] {
if (!mappedPixelData || mappedPixelData.length === 0) {
return [];
}
const M = mappedPixelData.length;
const N = mappedPixelData[0].length;
const visited = Array(M).fill(null).map(() => Array(N).fill(false));
const regions: { row: number; col: number }[][] = [];
for (let row = 0; row < M; row++) {
for (let col = 0; col < N; col++) {
if (!visited[row][col]) {
const currentCell = mappedPixelData[row][col];
if (currentCell && !currentCell.isExternal && currentCell.color === targetColor) {
const region = getConnectedRegion(mappedPixelData, row, col, targetColor);
if (region.length > 0) {
regions.push(region);
// 标记该区域的所有像素为已访问
region.forEach(({ row: r, col: c }) => {
visited[r][c] = true;
});
}
}
}
}
}
return regions;
}
// 检查区域是否完全已完成
export function isRegionCompleted(
region: { row: number; col: number }[],
completedCells: Set<string>
): boolean {
return region.every(({ row, col }) => completedCells.has(`${row},${col}`));
}
// 检查区域是否部分已完成
export function isRegionPartiallyCompleted(
region: { row: number; col: number }[],
completedCells: Set<string>
): boolean {
return region.some(({ row, col }) => completedCells.has(`${row},${col}`));
}
// 获取区域的中心点(用于定位和显示)
export function getRegionCenter(region: { row: number; col: number }[]): { row: number; col: number } {
if (region.length === 0) {
return { row: 0, col: 0 };
}
const totalRow = region.reduce((sum, cell) => sum + cell.row, 0);
const totalCol = region.reduce((sum, cell) => sum + cell.col, 0);
return {
row: Math.floor(totalRow / region.length),
col: Math.floor(totalCol / region.length)
};
}
// 根据距离排序区域(用于最近优先的引导模式)
export function sortRegionsByDistance(
regions: { row: number; col: number }[][],
referencePoint: { row: number; col: number }
): { row: number; col: number }[][] {
return regions.sort((a, b) => {
const centerA = getRegionCenter(a);
const centerB = getRegionCenter(b);
const distanceA = Math.abs(centerA.row - referencePoint.row) + Math.abs(centerA.col - referencePoint.col);
const distanceB = Math.abs(centerB.row - referencePoint.row) + Math.abs(centerB.col - referencePoint.col);
return distanceA - distanceB;
});
}
// 根据大小排序区域(用于最大优先的引导模式)
export function sortRegionsBySize(
regions: { row: number; col: number }[][]
): { row: number; col: number }[][] {
return regions.sort((a, b) => b.length - a.length);
}