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();
}
}
}