using System.Collections.Generic; using UnityEngine; namespace AibisDream { /// /// 放置验证器实现 /// 负责验证形状是否可以放置在指定位置 /// public class PlacementValidator : IPlacementValidator { /// /// 检查形状是否可以放置在指定位置 /// /// 网格系统 /// 要放置的形状 /// 网格X坐标(形状左下角位置) /// 网格Y坐标(形状左下角位置) /// 放置验证结果 public PlacementResult CanPlace(IBlockPuzzleGrid grid, IBlockShape shape, int gridX, int gridY) { if (grid == null || shape == null) { return PlacementResult.InvalidPosition; } // 获取形状的所有格子位置(相对坐标,基于形状的本地坐标系) Vector2Int[] blockPositions = shape.GetBlockPositions(); if (blockPositions == null || blockPositions.Length == 0) { return PlacementResult.InvalidPosition; } // 形状的坐标系统: // - GetBlockPositions() 返回的坐标中,(0, 0) 是形状的左上角(在pattern数组中) // - pattern[i, j] 中,i 是 x(从左到右),j 是 y(从上到下,j=0 是顶部) // - gridX, gridY 是形状左下角在网格中的位置 // - 需要将形状的相对坐标转换为网格坐标 foreach (var blockPos in blockPositions) { // 将形状的相对坐标转换为网格坐标 // 形状的 (0, 0) 对应网格的 (gridX, gridY + shape.Height - 1) // 形状的 (i, j) 对应网格的 (gridX + i, gridY + shape.Height - 1 - j) int gridCellX = gridX + blockPos.x; int gridCellY = gridY + shape.Height - 1 - blockPos.y; // 检查是否超出边界 if (!grid.IsValidPosition(gridCellX, gridCellY)) { return PlacementResult.OutOfBounds; } // 检查是否与已有块重叠 if (!grid.IsCellEmpty(gridCellX, gridCellY)) { return PlacementResult.Overlap; } } return PlacementResult.Success; } /// /// 检查形状是否可以放置在指定位置(详细版本) /// /// 网格系统 /// 要放置的形状 /// 网格X坐标(形状左下角位置) /// 网格Y坐标(形状左下角位置) /// 失败原因(如果返回false) /// 是否可以放置 public bool CanPlaceDetailed(IBlockPuzzleGrid grid, IBlockShape shape, int gridX, int gridY, out PlacementResult failureReason) { failureReason = CanPlace(grid, shape, gridX, gridY); return failureReason == PlacementResult.Success; } /// /// 获取形状在指定位置的所有占用格子坐标 /// /// 形状 /// 网格X坐标(形状左下角位置) /// 网格Y坐标(形状左下角位置) /// 占用格子的网格坐标数组 public (int x, int y)[] GetOccupiedCells(IBlockShape shape, int gridX, int gridY) { if (shape == null) { return new (int x, int y)[0]; } Vector2Int[] blockPositions = shape.GetBlockPositions(); if (blockPositions == null || blockPositions.Length == 0) { return new (int x, int y)[0]; } List<(int x, int y)> occupiedCells = new List<(int x, int y)>(); foreach (var blockPos in blockPositions) { // 将形状的相对坐标转换为网格坐标(左下角为基准) int gridCellX = gridX + blockPos.x; int gridCellY = gridY + shape.Height - 1 - blockPos.y; occupiedCells.Add((gridCellX, gridCellY)); } return occupiedCells.ToArray(); } } }