Hi, First, i'm new to Unity and C# scripting so i try to learn with a match-3 game. My game runs fine but i try to add some features : 1) Shuffle my grid when no more matches can be found; 2) Add the possibility to store possible matches so we can highlight one of them after some time; 3) Fill the grid even if there are ROCK blocks on top of the Grid; 4) Add the possibility to collect ingredients. Currently, my game has these features : - 6 different colors; - Vertical and horizontal "Bombs"; - Clear color "Bomb"; - Obstacles (called ICE in my game); - Unbreakable ROCK blocks (need to modify the FillStep() function to add support to these blocks); - Score based, obstacles based and time based levels. Here is my grid class (i think it's possible to fix 1), 2) and 3) just with this but 4) will need to show other scripts (like Level class) so it will be implemented later if someone accept to help ^^) Spoiler: Long code (Grid Class) Code (CSharp): using UnityEngine; using System.Collections; using System.Collections.Generic; public class Grid : MonoBehaviour { public enum PieceType { EMPTY, NORMAL, ICE, ROW_CLEAR, COLUMN_CLEAR, RAINBOW, NONE, ROCK, COUNT, }; [System.Serializable] public struct PiecePrefab { public PieceType type; public GameObject prefab; }; [System.Serializable] public struct PiecePosition { public PieceType type; public int x; public int y; }; // Grid size public int xDim; public int yDim; // Time to fill/refill the grid public float fillTime; // Used to call the level class public Level level; // Array of piece types that can be defined in the inspector public PiecePrefab[] piecePrefabs; // GameObject to set a background for our pieces public GameObject backgroundPrefab; // Used to set our initial pieces in the inspector, for each level public PiecePosition[] initialPieces; // Dictionary for attaching a piece to its prefab private Dictionary<PieceType, GameObject> piecePrefabDict; // 2D array to contain all our pieces private GamePiece[,] pieces; // Used to move pieces in diag (for filling a grid with obstacles) private bool inverse = false; // Used to know wich pieces will be swapped private GamePiece pressedPiece; private GamePiece enteredPiece; // Set the game over. Doesn't mean that the player loose private bool gameOver = false; // Use this for initialization void Awake () { piecePrefabDict = new Dictionary<PieceType, GameObject> (); // First we need to check if we have keys in our dictionary. If not, add them for (int i = 0; i < piecePrefabs.Length; i++) { if (!piecePrefabDict.ContainsKey (piecePrefabs [i].type)) { piecePrefabDict.Add (piecePrefabs [i].type, piecePrefabs [i].prefab); } } // Instantiate the background for all our pieces on the grid for (int x = 0; x < xDim; x++) { for (int y = 0; y < yDim; y++) { GameObject background = (GameObject)Instantiate (backgroundPrefab, GetWorldPosition(x, y), Quaternion.identity); background.transform.parent = transform; } } // Now we need to add our initial and empty pieces on the grid pieces = new GamePiece[xDim, yDim]; for (int i = 0; i < initialPieces.Length; i++) { if (initialPieces [i].x >= 0 && initialPieces [i].x < xDim && initialPieces [i].y >= 0 && initialPieces [i].y < yDim) { SpawnNewPiece (initialPieces [i].x, initialPieces [i].y, initialPieces [i].type); } } for (int x = 0; x < xDim; x++) { for (int y = 0; y < yDim; y++) { if (pieces [x, y] == null) { SpawnNewPiece (x, y, PieceType.EMPTY); } } } // Now the grid is filled with empty pieces, we need to replace them by our non-empty pieces with animation StartCoroutine(Fill ()); } // Update is called once per frame void Update () { } // Fill the grid public IEnumerator Fill() { bool needsRefill = true; while (needsRefill) { yield return new WaitForSeconds (fillTime); while (FillStep ()) { inverse = !inverse; yield return new WaitForSeconds (fillTime); } needsRefill = ClearAllValidMatches (); } CheckAllPossibleMatches (); } // Move a piece to fill the grid // Todo : add a check for ROCK Pieces so that they'll be ignored when filling the grid as they can't be destroyed and can be on top of the grid public bool FillStep() { bool movedPiece = false; for (int y = yDim-2; y >= 0; y--) { for (int loopX = 0; loopX < xDim; loopX++) { int x = loopX; if (inverse) { x = xDim - 1 - loopX; } GamePiece piece = pieces [x, y]; if (piece.IsMovable ()) { GamePiece pieceBelow = pieces [x, y + 1]; if (pieceBelow.Type == PieceType.EMPTY) { Destroy (pieceBelow.gameObject); piece.MovableComponent.Move (x, y + 1, fillTime); pieces [x, y + 1] = piece; SpawnNewPiece (x, y, PieceType.EMPTY); movedPiece = true; } else { for (int diag = -1; diag <= 1; diag++) { if (diag != 0) { int diagX = x + diag; if (inverse) { diagX = x - diag; } if (diagX >= 0 && diagX < xDim) { GamePiece diagonalPiece = pieces [diagX, y + 1]; if (diagonalPiece.Type == PieceType.EMPTY) { bool hasPieceAbove = true; for (int aboveY = y; aboveY >= 0; aboveY--) { GamePiece pieceAbove = pieces [diagX, aboveY]; if (pieceAbove.IsMovable ()) { break; } else if(!pieceAbove.IsMovable() && pieceAbove.Type != PieceType.EMPTY) { hasPieceAbove = false; break; } } if (!hasPieceAbove) { Destroy (diagonalPiece.gameObject); piece.MovableComponent.Move (diagX, y + 1, fillTime); pieces [diagX, y + 1] = piece; SpawnNewPiece (x, y, PieceType.EMPTY); movedPiece = true; break; } } } } } } } } } for (int x = 0; x < xDim; x++) { GamePiece pieceBelow = pieces [x, 0]; if (pieceBelow.Type == PieceType.EMPTY) { Destroy (pieceBelow.gameObject); GameObject newPiece = (GameObject)Instantiate(piecePrefabDict[PieceType.NORMAL], GetWorldPosition(x, -1), Quaternion.identity); newPiece.transform.parent = transform; pieces [x, 0] = newPiece.GetComponent<GamePiece> (); pieces [x, 0].Init (x, -1, this, PieceType.NORMAL); pieces [x, 0].MovableComponent.Move (x, 0, fillTime); pieces [x, 0].ColorComponent.SetColor ((ColorPiece.ColorType)Random.Range (0, pieces [x, 0].ColorComponent.NumColors)); movedPiece = true; } } return movedPiece; } // Used to get the offset of our pieces public Vector2 GetWorldPosition(int x, int y) { return new Vector2 (transform.position.x - xDim / 2.0f + x, transform.position.y + yDim / 2.0f - y); } // Spawn a new piece public GamePiece SpawnNewPiece(int x, int y, PieceType type) { GameObject newPiece = (GameObject)Instantiate (piecePrefabDict [type], GetWorldPosition (x, y), Quaternion.identity); newPiece.transform.parent = transform; pieces [x, y] = newPiece.GetComponent<GamePiece> (); pieces [x, y].Init (x, y, this, type); return pieces [x, y]; } // Used to know if piece1 is adjacent to piece2 public bool IsAdjacent(GamePiece piece1, GamePiece piece2) { return (piece1.X == piece2.X && (int)Mathf.Abs (piece1.Y - piece2.Y) == 1) || (piece1.Y == piece2.Y && (int)Mathf.Abs (piece1.X - piece2.X) == 1); } // Swap pieces if they are adjacent public void SwapPieces(GamePiece piece1, GamePiece piece2) { // If the game is over, just disabled this function if (gameOver) { return; } // Swap only if they are movable if (piece1.IsMovable () && piece2.IsMovable ()) { pieces [piece1.X, piece1.Y] = piece2; pieces [piece2.X, piece2.Y] = piece1; if (GetMatch (piece1, piece2.X, piece2.Y) != null || GetMatch (piece2, piece1.X, piece1.Y) != null || piece1.Type == PieceType.RAINBOW || piece2.Type == PieceType.RAINBOW) { int piece1X = piece1.X; int piece1Y = piece1.Y; // Make some animation while swaping piece1.MovableComponent.Move (piece2.X, piece2.Y, fillTime); piece2.MovableComponent.Move (piece1X, piece1Y, fillTime); // Clear the Rainbow piece manually before clearing matches if (piece1.Type == PieceType.RAINBOW && piece1.IsClearable () && piece2.IsColored ()) { ClearColorPiece clearColor = piece1.GetComponent<ClearColorPiece> (); if (clearColor) { clearColor.Color = piece2.ColorComponent.Color; } ClearPiece (piece1.X, piece1.Y); } if (piece2.Type == PieceType.RAINBOW && piece2.IsClearable () && piece1.IsColored ()) { ClearColorPiece clearColor = piece2.GetComponent<ClearColorPiece> (); if (clearColor) { clearColor.Color = piece1.ColorComponent.Color; } ClearPiece (piece2.X, piece2.Y); } // Now we need to clear all pieces from this match ClearAllValidMatches (); if (piece1.Type == PieceType.ROW_CLEAR || piece1.Type == PieceType.COLUMN_CLEAR) { ClearPiece (piece1.X, piece1.Y); } if (piece2.Type == PieceType.ROW_CLEAR || piece2.Type == PieceType.COLUMN_CLEAR) { ClearPiece (piece2.X, piece2.Y); } pressedPiece = null; enteredPiece = null; // And finally refilling the board StartCoroutine (Fill ()); // Declares a player move level.OnMove(); } else { // No match, return pieces to their own positions pieces [piece1.X, piece1.Y] = piece1; pieces [piece2.X, piece2.Y] = piece2; } } } // Assign piece when piece is pressed public void PressPiece(GamePiece piece) { pressedPiece = piece; } // Assign piece when piece is entered public void EnterPiece(GamePiece piece) { enteredPiece = piece; } // Swap pieces when piece is released public void ReleasePiece() { if (IsAdjacent (pressedPiece, enteredPiece)) { SwapPieces (pressedPiece, enteredPiece); } } // Used to know if pieces can match public List<GamePiece> GetMatch(GamePiece piece, int newX, int newY) { if (piece.IsColored ()) { ColorPiece.ColorType color = piece.ColorComponent.Color; List<GamePiece> horizontalPieces = new List<GamePiece> (); List<GamePiece> verticalPieces = new List<GamePiece> (); List<GamePiece> matchingPieces = new List<GamePiece> (); // First check horizontal horizontalPieces.Add(piece); for (int dir = 0; dir <= 1; dir++) { for (int xOffset = 1; xOffset < xDim; xOffset++) { int x; if (dir == 0) { // Left x = newX - xOffset; } else { // Right x = newX + xOffset; } if (x < 0 || x >= xDim) { break; } if (pieces [x, newY].IsColored () && pieces [x, newY].ColorComponent.Color == color) { horizontalPieces.Add (pieces [x, newY]); } else { break; } } } if (horizontalPieces.Count >= 3) { for (int i = 0; i < horizontalPieces.Count; i++) { matchingPieces.Add (horizontalPieces [i]); } } // Traverse vertically if we found a match (for L and T shapes) if (horizontalPieces.Count >= 3) { for (int i = 0; i < horizontalPieces.Count; i++) { for (int dir = 0; dir <= 1; dir++) { for (int yOffset = 1; yOffset < yDim; yOffset++) { int y; if (dir == 0) { // Up y = newY - yOffset; } else { // Down y = newY + yOffset; } if (y < 0 || y >= yDim) { break; } if (pieces [horizontalPieces [i].X, y].IsColored () && pieces [horizontalPieces [i].X, y].ColorComponent.Color == color) { verticalPieces.Add (pieces [horizontalPieces [i].X, y]); } else { break; } } } if (verticalPieces.Count < 2) { verticalPieces.Clear (); } else { for (int j = 0; j < verticalPieces.Count; j++) { matchingPieces.Add (verticalPieces [j]); } break; } } } if (matchingPieces.Count >= 3) { return matchingPieces; } // Didn't find anything going horizontally first, // so now check vertically horizontalPieces.Clear(); verticalPieces.Clear (); verticalPieces.Add(piece); for (int dir = 0; dir <= 1; dir++) { for (int yOffset = 1; yOffset < yDim; yOffset++) { int y; if (dir == 0) { // Up y = newY - yOffset; } else { // Down y = newY + yOffset; } if (y < 0 || y >= yDim) { break; } if (pieces [newX, y].IsColored () && pieces [newX, y].ColorComponent.Color == color) { verticalPieces.Add (pieces [newX, y]); } else { break; } } } if (verticalPieces.Count >= 3) { for (int i = 0; i < verticalPieces.Count; i++) { matchingPieces.Add (verticalPieces [i]); } } // Traverse horizontally if we found a match (for L and T shapes) if (verticalPieces.Count >= 3) { for (int i = 0; i < verticalPieces.Count; i++) { for (int dir = 0; dir <= 1; dir++) { for (int xOffset = 1; xOffset < xDim; xOffset++) { int x; if (dir == 0) { // Left x = newX - xOffset; } else { // Right x = newX + xOffset; } if (x < 0 || x >= xDim) { break; } if (pieces [x, verticalPieces[i].Y].IsColored () && pieces [x, verticalPieces[i].Y].ColorComponent.Color == color) { horizontalPieces.Add (pieces [x, verticalPieces[i].Y]); } else { break; } } } if (horizontalPieces.Count < 2) { horizontalPieces.Clear (); } else { for (int j = 0; j < horizontalPieces.Count; j++) { matchingPieces.Add (horizontalPieces [j]); } break; } } } if (matchingPieces.Count >= 3) { return matchingPieces; } } return null; } // Clear all matches for one player move public bool ClearAllValidMatches() { bool needsRefill = false; for (int y = 0; y < yDim; y++) { for (int x = 0; x < xDim; x++) { if (pieces [x, y].IsClearable ()) { List<GamePiece> match = GetMatch (pieces [x, y], x, y); if (match != null) { // Start Special piece spawning PieceType specialPieceType = PieceType.COUNT; GamePiece randomPiece = match [Random.Range (0, match.Count)]; int specialPieceX = randomPiece.X; int specialPieceY = randomPiece.Y; if (match.Count == 4) { if (pressedPiece == null || enteredPiece == null) { specialPieceType = (PieceType)Random.Range ((int)PieceType.ROW_CLEAR, (int)PieceType.COLUMN_CLEAR); } else if (pressedPiece.Y == enteredPiece.Y) { specialPieceType = PieceType.ROW_CLEAR; } else { specialPieceType = PieceType.COLUMN_CLEAR; } } else if (match.Count >= 5) { specialPieceType = PieceType.RAINBOW; } // End Special piece spawning for (int i = 0; i < match.Count; i++) { if (ClearPiece (match [i].X, match [i].Y)) { needsRefill = true; if (match [i] == pressedPiece || match [i] == enteredPiece) { specialPieceX = match [i].X; specialPieceY = match [i].Y; } } } // Spawn the special piece if (specialPieceType != PieceType.COUNT) { Destroy (pieces [specialPieceX, specialPieceY]); GamePiece newPiece = SpawnNewPiece (specialPieceX, specialPieceY, specialPieceType); if ((specialPieceType == PieceType.ROW_CLEAR || specialPieceType == PieceType.COLUMN_CLEAR) && newPiece.IsColored () && match [0].IsColored ()) { newPiece.ColorComponent.SetColor(match[0].ColorComponent.Color); } else if (specialPieceType == PieceType.RAINBOW && newPiece.IsColored ()) { newPiece.ColorComponent.SetColor (ColorPiece.ColorType.ANY); } } } } } } return needsRefill; } // Clear a piece and respawn an empty piece public bool ClearPiece(int x, int y) { if (pieces [x, y].IsClearable () && !pieces [x, y].ClearableComponent.IsBeingCleared) { pieces [x, y].ClearableComponent.Clear (); SpawnNewPiece (x, y, PieceType.EMPTY); ClearObstacles (x, y); return true; } return false; } // Used to clear Ice pieces public void ClearObstacles(int x, int y) { for (int adjacentX = x - 1; adjacentX <= x + 1; adjacentX++) { if (adjacentX != x && adjacentX >= 0 && adjacentX < xDim) { if (pieces [adjacentX, y].Type == PieceType.ICE && pieces [adjacentX, y].IsClearable ()) { pieces [adjacentX, y].ClearableComponent.Clear (); SpawnNewPiece (adjacentX, y, PieceType.EMPTY); } } } for (int adjacentY = y - 1; adjacentY <= y + 1; adjacentY++) { if (adjacentY != y && adjacentY >= 0 && adjacentY < yDim) { if (pieces [x, adjacentY].Type == PieceType.ICE && pieces [x, adjacentY].IsClearable ()) { pieces [x, adjacentY].ClearableComponent.Clear (); SpawnNewPiece (x, adjacentY, PieceType.EMPTY); } } } } // Clear entire row public void ClearRow(int row) { for (int x = 0; x < xDim; x++) { ClearPiece (x, row); } } // Clear entire column public void ClearColumn(int column) { for (int y = 0; y < yDim; y++) { ClearPiece (column, y); } } // Clear all pieces with the same color public void ClearColor(ColorPiece.ColorType color) { for (int x = 0; x < xDim; x++) { for (int y = 0; y < yDim; y++) { if (pieces [x, y].IsColored () && (pieces [x, y].ColorComponent.Color == color || color == ColorPiece.ColorType.ANY)) { ClearPiece (x, y); } } } } // Set the game over so the current level ends public void GameOver() { gameOver = true; } // Returns a list of pieces on the grid with the given type parameter public List<GamePiece> GetPiecesOfType(PieceType type) { List<GamePiece> piecesOfType = new List<GamePiece> (); for (int x = 0; x < xDim; x++) { for (int y = 0; y < yDim; y++) { if (pieces [x, y].Type == type) { piecesOfType.Add (pieces [x, y]); } } } return piecesOfType; } // Used to know if two pieces have the same color public bool IsSameColor(int x, int y, int color) { if (pieces [x, y].IsColored ()) { return (int)pieces [x, y].ColorComponent.Color == color; } else { return false; } } // Used to check all possible matches on the grid public void CheckAllPossibleMatches() { // If the game is over, just disabled this function if (gameOver) { return; } // Vertical check for (int x = 0; x < xDim; x++) { int secondToLastType = -1; int lastType = -2; int currentType = -3; for (int y = 0; y < yDim; y++) { // Only if piece is colored and clearable if (pieces [x, y].IsClearable () && pieces [x, y].IsColored ()) { currentType = (int)pieces [x, y].ColorComponent.Color; if (lastType == currentType) { if ((y > 2 && y < yDim - 3) && (x > 1 && x < xDim)) { /* * & * * * * * * * & * * * & * * */ if (IsSameColor (x, y - 3, currentType)) return; /* * * * * * * & * * & * * * & * * */ if (IsSameColor (x + 1, y - 2, currentType)) return; /* * * * * & * * * * & * * * & * * */ if (IsSameColor (x - 1, y - 2, currentType)) return; /* * & * * * & * * * * * * * & * * */ if (IsSameColor (x, y + 2, currentType)) return; /* * & * * * & * * * * & * * * * * */ if (IsSameColor (x + 1, y + 1, currentType)) return; /* * & * * * & * * & * * * * * * * */ if (IsSameColor (x - 1, y + 1, currentType)) return; } } else if (secondToLastType == currentType) { if (y > 1 && (x > 0 && x < xDim - 1)) { /* * & * * * * & * * & * * * * * * */ if (IsSameColor (x + 1, y - 1, currentType)) return; Debug.Log ("VCheck8 " + (x - 1) + "," + (y - 1)); /* * & * * & * * * * & * * * * * * */ if (IsSameColor (x - 1, y - 1, currentType)) return; } } secondToLastType = lastType; lastType = currentType; } } } // Horizontal check for (int y = 0; y < yDim; y++) { int secondToLastType = -1; int lastType = -2; int currentType = -3; for (int x = 0; x < xDim; x++) { // Only if piece is colored and clearable if (pieces [x, y].IsClearable () && pieces [x, y].IsColored ()) { currentType = (int)pieces [x, y].ColorComponent.Color; if (lastType == currentType) { if ((x > 2 && x < xDim - 3) && (y > 1 && y < yDim)) { /* * & * & & * */ if (IsSameColor (x - 3, y, currentType)) return; /* * * * & & * * * & * * * */ if (IsSameColor (x - 2, y + 1, currentType)) return; /* * * & * * * * * * & & * */ if (IsSameColor (x - 2, y - 1, currentType)) return; /* * & & * & * */ if (IsSameColor (x + 2, y, currentType)) return; /* * & & * * * * * * & * */ if (IsSameColor (x + 1, y + 1, currentType)) return; /* * * * & * * * & & * * * */ if (IsSameColor (x + 1, y - 1, currentType)) return; } } else if (secondToLastType == currentType) { if (x > 1 && (y > 0 && y < yDim - 1)) { /* * & * & * * * * & * * * */ if (IsSameColor (x - 1, y + 1, currentType)) return; /* * * & * * * * & * & * * */ if (IsSameColor (x - 1, y - 1, currentType)) return; } } secondToLastType = lastType; lastType = currentType; } } } // No matches? Shuffle! Shuffle(); } // Shuffle the grid public void Shuffle() { Debug.Log ("No More Matches, shuffle the grid"); for (int x = 0; x < xDim; x++) { for (int y = 0; y < yDim; y++) { // We only need to shuffle movable pieces if (pieces [x, y].IsMovable ()) { pieces [x, y].ColorComponent.SetColor((ColorPiece.ColorType)Random.Range(0, 5)); } if (ClearAllValidMatches ()) StartCoroutine (Fill ()); } } } } 1) I think there is a problem with my CheckAllPossibleMatches() function. It works most of the time but sometimes shuffle even if we have one possible match on the grid. And sometimes, the game crash with an error : For my current test, i have set the grid to be 9x9 so x and y are in the [0,8] range. That's why i've made some checks to avoid such problems but it seems i've failed. 2) Currently, we can't save possible matches in an array to choose one to highlight if the player don't move. 3) Currently, if we add some ROCK blocks on top of the grid, it can't be filled. Is there a way to bypass ROCK blocks ? 4) Later, we have enough problems to solve right now ^^
So your pieces are all just solid blocks of color ? I noticed you mention somewhere in the code checking for L-shapes and T-shapes? Is this just a game where I have 3 colored blocks in a row, horizontally or vertically and If i do destroy them + all adjacent blocks of a the same color (say I had a cross?). What if I make a 3 in a row that had 2 of the same color directly below it: GRG RBR RR Then swapping the middle It turns into this: GBG RRR RR would all 5 blow up?
First thanks for your reply. No, here are the matches : Horizontal matches : Vertical matches : And 2 more diagonal matches : EDIT : Grid class edited to fix some minor bugs. But not the one i've asked for help :'(
I've edited the Grid class and added match patterns so it's now well commented. EDIT : adding more comments but editing the OP failed so... For vertical check : Code (CSharp): /* * First loop : currentType will take the value of Piece [x,0] color * We don't make a match test here. At the end of this first loop, we'll pass the currentType value to lastType * Second loop : currentType will take the value of Piece [x,1] color * We can now check if lastType == currentType and make some matching tests but we can't test the duag patterns as we don't have secondLastType set right now * At the end of this loop, we'll set secondLastType with lastType value and continue to set lastType value to currentType * Third loop : currentType will take the value of Piece [x,2] color * We can now check if lastType == currentType and make all matching tests as secondLastType is set */ For horizontal check : Code (CSharp): /* * First loop : currentType will take the value of Piece [0,y] color * We don't make a match test here. At the end of this first loop, we'll pass the currentType value to lastType * Second loop : currentType will take the value of Piece [1,y] color * We can now check if lastType == currentType and make some matching tests but we can't test the duag patterns as we don't have secondLastType set right now * At the end of this loop, we'll set secondLastType with lastType value and continue to set lastType value to currentType * Third loop : currentType will take the value of Piece [2,y] color * We can now check if lastType == currentType and make all matching tests as secondLastType is set */
Without going through your code, here's how I'd do it. No disrespect meant, feel free to use it or not I assume all of your blocks are holding some kind of grid position value and an ID value that represents their colour or whatever. Say you have 3x3 matrix using 0, 1, 2 to represents row/columns. (Left to right, bottom to top) Top row has blue, blue, red Mid row has whatever, whatever, blue The user tries to swap (2, 2) with (2, 1) to create a blue match on the top row. Create a function that takes an ID parameter along with a position. Run it twice, once for each swapped blocks. In our case, we would feed it the blue identifier with the position (2, 2), since we're trying to swap the blue and red of the last column, and then we would feed it the red identifier with the position (1, 2). Assuming you are only going for matches that are in a straight line, the functions should run 2 scans, 1 horizontal and 1 vertical. I threw this together real quick, it's untested. I'm leaving home but I'll check back tonight in case you decide to use it and you encounter issues. Code (CSharp): void FindMatches (int ID, Vector2 gridPos) { //List that holds the confirmed matches List <Vector2> matches = new List<Vector2> (); //temporary list to hold the potential horizontal matches List <Vector2> tempHoriz = new List<Vector2> (); //flags to know when to stop iterating in a direction //In this case, 0 represents left, 1 represents right bool[] dirFlag = new bool[2]; dirFlag [0] = false; dirFlag [1] = false; for (int i = 0; i < whateveryourgridsizeis; i++) { //Create offsets to scan based on the iterator Vector2[] offSet = new Vector2[2]; offSet [0] = gridPos + new Vector2 (-i, 0); offSet [1] = gridPos + new Vector2 (i, 0); for (int j = 0; j < 2; j++) { //if the flag isnt true, you can keep iterating in that direction if (!dirFlag [j] == false) { //Assuming you have a dictionary that goes a bit like (position, blockclassinstance) //Get the block instance from it, whatever your setup is BlockClass temp = GetBlock (offSet[j]); //nullcheck since depending on where your initial grid position is, you will definitely iterate outside of boundaries and get nulls if (temp != null) { //Access its identifier(however you set it up) and compare it with the parameter fed to the function to see if they match if (temp.ID == ID) { //You have a match, add it to the horizontal temporary list tempHoriz.Add (offSet[j]); } else { //The block doesn't match, you want to stop iterating that way dirFlag[j] = true; } } else { dirFlag[j] = true; } } } //If both flags are true, no point in running the function anymore if (dirFlag [0] && dirFlag [1]) { break; } } //Now check to see if your temporary horizontal list has at least 3 values if (tempHoriz.Count >= 3) { //You have a match, add them to the matches list } //Repeat everything but vertically //If your vertical list is a match as well, you can throw them all in the same list, most likely you have some kind of T shaped match }
Thanks This is exactly what i've done in my grid class (see the getMatch function). I don't have problem making matches, i've already written all the code needed to do that. I only need to check if there are still one or more matches on the grid and store them in an array. Edit : oh ! Looks like this is what your code do... l'll try to modify if to suit my code. Please, look through my code. If someone wants all the project code, i can send a zip file with all the scripts i'm using. And sorry for my bad english...