Cleanup
This commit is contained in:
@@ -3,21 +3,41 @@ using System.Linq;
|
||||
using Enums;
|
||||
using Models.Interfaces;
|
||||
using Services.Interfaces;
|
||||
using Structs;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Services {
|
||||
public class MatchService : IMatchService {
|
||||
private List<Gem> currentMatches = new List<Gem>();
|
||||
public List<Gem> CurrentMatches => this.currentMatches;
|
||||
|
||||
public List<BombSpawnRequest> pendingBombSpawns = new List<BombSpawnRequest>();
|
||||
public IReadOnlyList<BombSpawnRequest> PendingBombSpawns => this.pendingBombSpawns;
|
||||
|
||||
private Vector2Int lastSwapFrom;
|
||||
private Vector2Int lastSwapTo;
|
||||
|
||||
private IGameBoard gameBoard;
|
||||
|
||||
public MatchService(IGameBoard gameBoard) {
|
||||
this.gameBoard = gameBoard;
|
||||
}
|
||||
|
||||
public void SetLastSwap(Vector2Int from, Vector2Int to) {
|
||||
this.lastSwapFrom = from;
|
||||
this.lastSwapTo = to;
|
||||
}
|
||||
|
||||
public void ClearPendingBombs() {
|
||||
this.pendingBombSpawns.Clear();
|
||||
}
|
||||
|
||||
public bool MatchesAt(Vector2Int positionToCheck, GemType gemTypeToCheck) {
|
||||
Gem[,] gems = this.gameBoard.GemsGrid;
|
||||
|
||||
if (gemTypeToCheck == GemType.Bomb)
|
||||
return false;
|
||||
|
||||
if (positionToCheck.x > 1)
|
||||
{
|
||||
if (gems[positionToCheck.x - 1, positionToCheck.y].Type == gemTypeToCheck && gems[positionToCheck.x - 2, positionToCheck.y].Type == gemTypeToCheck)
|
||||
@@ -35,59 +55,102 @@ namespace Services {
|
||||
|
||||
public void FindAllMatches() {
|
||||
this.currentMatches.Clear();
|
||||
this.pendingBombSpawns.Clear();
|
||||
|
||||
for (int x = 0; x < this.gameBoard.Width; x++)
|
||||
for (int y = 0; y < this.gameBoard.Height; y++)
|
||||
{
|
||||
for (int y = 0; y < this.gameBoard.Height; y++) {
|
||||
Gem currentGem = this.gameBoard.GemsGrid[x, y];
|
||||
if (currentGem != null)
|
||||
{
|
||||
if (x > 0 && x < this.gameBoard.Width - 1)
|
||||
{
|
||||
Gem leftGem = this.gameBoard.GemsGrid[x - 1, y];
|
||||
Gem rightGem = this.gameBoard.GemsGrid[x + 1, y];
|
||||
//checking no empty spots
|
||||
if (leftGem != null && rightGem != null)
|
||||
{
|
||||
//Match
|
||||
if (leftGem.Type == currentGem.Type && rightGem.Type == currentGem.Type)
|
||||
{
|
||||
currentGem.isMatch = true;
|
||||
leftGem.isMatch = true;
|
||||
rightGem.isMatch = true;
|
||||
this.currentMatches.Add(currentGem);
|
||||
this.currentMatches.Add(leftGem);
|
||||
this.currentMatches.Add(rightGem);
|
||||
}
|
||||
if (currentGem == null)
|
||||
continue;
|
||||
|
||||
if (x > 0 && x < this.gameBoard.Width - 1) {
|
||||
Gem leftGem = this.gameBoard.GemsGrid[x - 1, y];
|
||||
Gem rightGem = this.gameBoard.GemsGrid[x + 1, y];
|
||||
if (leftGem != null && rightGem != null) {
|
||||
if (leftGem.MatchColor == currentGem.MatchColor && rightGem.MatchColor == currentGem.MatchColor) {
|
||||
this.currentMatches.Add(currentGem);
|
||||
this.currentMatches.Add(leftGem);
|
||||
this.currentMatches.Add(rightGem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (y > 0 && y < this.gameBoard.Height - 1)
|
||||
{
|
||||
Gem aboveGem = this.gameBoard.GemsGrid[x, y - 1];
|
||||
Gem bellowGem = this.gameBoard.GemsGrid[x, y + 1];
|
||||
//checking no empty spots
|
||||
if (aboveGem != null && bellowGem != null)
|
||||
{
|
||||
//Match
|
||||
if (aboveGem.Type == currentGem.Type && bellowGem.Type == currentGem.Type)
|
||||
{
|
||||
currentGem.isMatch = true;
|
||||
aboveGem.isMatch = true;
|
||||
bellowGem.isMatch = true;
|
||||
this.currentMatches.Add(currentGem);
|
||||
this.currentMatches.Add(aboveGem);
|
||||
this.currentMatches.Add(bellowGem);
|
||||
}
|
||||
if (y > 0 && y < this.gameBoard.Height - 1) {
|
||||
Gem aboveGem = this.gameBoard.GemsGrid[x, y - 1];
|
||||
Gem bellowGem = this.gameBoard.GemsGrid[x, y + 1];
|
||||
if (aboveGem != null && bellowGem != null) {
|
||||
if (aboveGem.MatchColor == currentGem.MatchColor && bellowGem.MatchColor == currentGem.MatchColor) {
|
||||
this.currentMatches.Add(currentGem);
|
||||
this.currentMatches.Add(aboveGem);
|
||||
this.currentMatches.Add(bellowGem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.currentMatches.Count > 0) this.currentMatches = this.currentMatches.Distinct().ToList();
|
||||
if (this.currentMatches.Count > 0)
|
||||
this.currentMatches = this.currentMatches.Distinct().ToList();
|
||||
|
||||
DetectBombSpawnFromLastSwap();
|
||||
CheckForBombs();
|
||||
}
|
||||
|
||||
private void DetectBombSpawnFromLastSwap() {
|
||||
Vector2Int from = this.lastSwapFrom;
|
||||
Vector2Int to = this.lastSwapTo;
|
||||
|
||||
TryCreateBombSpawnAt(from);
|
||||
TryCreateBombSpawnAt(to);
|
||||
}
|
||||
|
||||
private void TryCreateBombSpawnAt(Vector2Int pivot) {
|
||||
Gem pivotGem = this.gameBoard.GetGemAt(pivot);
|
||||
if (pivotGem == null)
|
||||
return;
|
||||
|
||||
// If it's already a bomb, don't create another.
|
||||
if (pivotGem.Type == GemType.Bomb)
|
||||
return;
|
||||
|
||||
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)
|
||||
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 CountLine(Vector2Int start, Vector2Int direction) {
|
||||
Gem startGem = this.gameBoard.GetGemAt(start);
|
||||
if (startGem == null)
|
||||
return 0;
|
||||
|
||||
GemType color = startGem.MatchColor;
|
||||
|
||||
int count = 0;
|
||||
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;
|
||||
|
||||
count++;
|
||||
position += direction;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
private void CheckForBombs() {
|
||||
Gem[,] gems = this.gameBoard.GemsGrid;
|
||||
@@ -118,32 +181,38 @@ namespace Services {
|
||||
|
||||
Gem neighbor = gems[newX, newY];
|
||||
if (neighbor?.Type == GemType.Bomb)
|
||||
MarkBombArea(new Vector2Int(newX, newY), 1);
|
||||
MarkBombCross(new Vector2Int(newX, newY), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void MarkBombArea(Vector2Int bombPosition, int blastSize) {
|
||||
|
||||
private void MarkBombCross(Vector2Int bombPosition, int radius) {
|
||||
Gem[,] gems = this.gameBoard.GemsGrid;
|
||||
int width = this.gameBoard.Width;
|
||||
int height = this.gameBoard.Height;
|
||||
|
||||
for (int x = bombPosition.x - blastSize; x <= bombPosition.x + blastSize; x++)
|
||||
{
|
||||
for (int y = bombPosition.y - blastSize; y <= bombPosition.y + blastSize; y++)
|
||||
{
|
||||
if (x >= 0 && x < width && y >= 0 && y < height)
|
||||
{
|
||||
if (gems[x, y] != null)
|
||||
{
|
||||
gems[x, y].isMatch = true;
|
||||
this.currentMatches.Add(gems[x, y]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Mark(Vector2Int p) {
|
||||
if (p.x < 0 || p.x >= width || p.y < 0 || p.y >= height)
|
||||
return;
|
||||
Gem g = gems[p.x, p.y];
|
||||
if (g == null)
|
||||
return;
|
||||
|
||||
this.currentMatches.Add(g);
|
||||
}
|
||||
|
||||
Mark(bombPosition);
|
||||
|
||||
for (int i = 1; i <= radius; i++) {
|
||||
Mark(bombPosition + Vector2Int.left * i);
|
||||
Mark(bombPosition + Vector2Int.right * i);
|
||||
Mark(bombPosition + Vector2Int.up * i);
|
||||
Mark(bombPosition + Vector2Int.down * i);
|
||||
}
|
||||
|
||||
this.currentMatches = this.currentMatches.Distinct().ToList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user