Implement L and T Shapes

This commit is contained in:
2025-12-16 21:44:49 +08:00
parent 9842e7ef3f
commit fffe1987b4
2 changed files with 124 additions and 9 deletions

View File

@@ -183,10 +183,10 @@ namespace Services {
private async UniTask DestroyMatchesAsync(List<Vector2Int> protectedPositions) {
List<Vector2Int> matchPositions = new List<Vector2Int>(this.matchService.CurrentMatches.Count);
for (int i = 0; i < this.matchService.CurrentMatches.Count; i++) {
var m = this.matchService.CurrentMatches[i];
if (m == null) continue;
Gem match = this.matchService.CurrentMatches[i];
if (match == null) continue;
Vector2Int pos = m.Position;
Vector2Int pos = match.Position;
if (protectedPositions != null && protectedPositions.Contains(pos))
continue;

View File

@@ -88,12 +88,80 @@ namespace Services {
}
}
if (this.currentMatches.Count > 0)
this.currentMatches = this.currentMatches.Distinct().ToList();
ExpandMatchesForLTShapes();
if (this.currentMatches.Count > 0)
this.currentMatches = this.currentMatches.Distinct().ToList();
DetectBombSpawnFromLastSwap();
}
private void ExpandMatchesForLTShapes() {
if (this.currentMatches.Count == 0)
return;
List<Gem> seeds = this.currentMatches.ToList();
foreach (Gem pivotGem in seeds) {
if (pivotGem == null)
continue;
Vector2Int pivot = pivotGem.Position;
int left = CountLine(pivot, Vector2Int.left);
int right = CountLine(pivot, Vector2Int.right);
int up = CountLine(pivot, Vector2Int.up);
int down = CountLine(pivot, Vector2Int.down);
int horizontalLen = left + 1 + right;
int verticalLen = up + 1 + down;
bool hasHorizontalMatch = horizontalLen >= 3;
bool hasVerticalMatch = verticalLen >= 3;
// one more in the perpendicular direction = length = 2
bool hasHorizontalArm = horizontalLen >= 2;
bool hasVerticalArm = verticalLen >= 2;
// Main horizontal + vertical arm = include vertical run
if (hasHorizontalMatch && hasVerticalArm) {
AddRun(pivot, Vector2Int.up);
AddRun(pivot, Vector2Int.down);
this.currentMatches.Add(pivotGem);
}
// Main vertical + horizontal arm = include horizontal run
if (hasVerticalMatch && hasHorizontalArm) {
AddRun(pivot, Vector2Int.left);
AddRun(pivot, Vector2Int.right);
this.currentMatches.Add(pivotGem);
}
}
}
private void AddRun(Vector2Int start, Vector2Int direction) {
Gem startGem = this.gameBoard.GetGemAt(start);
if (startGem == null)
return;
GemType color = startGem.MatchColor;
Vector2Int position = start + direction;
while (position.x >= 0 && position.x < this.gameBoard.Width &&
position.y >= 0 && position.y < this.gameBoard.Height) {
Gem g = this.gameBoard.GetGemAt(position);
if (g == null || g.MatchColor != color)
break;
this.currentMatches.Add(g);
position += direction;
}
}
private void DetectBombSpawnFromLastSwap() {
Vector2Int from = this.lastSwapFrom;
Vector2Int to = this.lastSwapTo;
@@ -114,20 +182,67 @@ namespace Services {
if (this.currentMatches.All(g => g.Position != pivot))
return;
int horizontal = CountLine(pivot, Vector2Int.left) + 1 + CountLine(pivot, Vector2Int.right);
int vertical = CountLine(pivot, Vector2Int.up) + 1 + CountLine(pivot, Vector2Int.down);
int best = Mathf.Max(horizontal, vertical);
if (best < 4)
// NEW RULE:
// If the match group that includes this pivot (including L/T expansions) has 4+ gems, spawn a bomb.
int groupSize = GetMatchedGroupSizeIncludingLT(pivot);
if (groupSize < 4)
return;
// Spawn a bomb on the creating slot with the same color group.
// Prevent duplicates for the same cell.
if (this.pendingBombSpawns.Any(b => b.Position == pivot))
return;
this.pendingBombSpawns.Add(new BombSpawnRequest(pivot, pivotGem.MatchColor));
}
private int GetMatchedGroupSizeIncludingLT(Vector2Int pivot) {
Gem pivotGem = this.gameBoard.GetGemAt(pivot);
if (pivotGem == null)
return 0;
GemType color = pivotGem.MatchColor;
// Only count gems that are actually in currentMatches (which already includes L/T expansions).
HashSet<Vector2Int> matchedPositions = new HashSet<Vector2Int>(
this.currentMatches
.Where(g => g != null && g.MatchColor == color)
.Select(g => g.Position)
);
if (!matchedPositions.Contains(pivot))
return 0;
Queue<Vector2Int> queue = new Queue<Vector2Int>();
HashSet<Vector2Int> visited = new HashSet<Vector2Int>();
queue.Enqueue(pivot);
visited.Add(pivot);
Vector2Int[] directions = {
Vector2Int.left,
Vector2Int.right,
Vector2Int.up,
Vector2Int.down
};
while (queue.Count > 0) {
Vector2Int currentPivot = queue.Dequeue();
for (int i = 0; i < directions.Length; i++) {
Vector2Int n = currentPivot + directions[i];
if (visited.Contains(n))
continue;
if (!matchedPositions.Contains(n))
continue;
visited.Add(n);
queue.Enqueue(n);
}
}
return visited.Count;
}
private int CountLine(Vector2Int start, Vector2Int direction) {
Gem startGem = this.gameBoard.GetGemAt(start);