I need help with a tile-matching game - how to match 2-3 different tiles?(not same 3 tile in row)

Hello everyone! I am new to unity and currently making a game based on 3-in-row matching game.
But instead of matching 3 tiles of same color and shape, my plan is to match tiles with different letters to form a syllable. So my game should help users to learn alphabet, but it looks like 3-in-row.
I basically use the code from this tutorial, I guess its very famous, as I run into this code everywhere in the Internet. Really great tutorial!

So the current method is isMatched, Find Matches();
Is there any way I can adopt it to look for not the same tiles, but to check the right combinations of consonants and vowels which form a syllable? Or if its impossible to adopt isMacthed, to which method should I change it? Thank you!

So I ll provide my scripts for better understanding.
Here are my letter and board scripts:

  1. letter
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Letter : MonoBehaviour
{
	[Header("BoardVariables")]
	public int column;
	public int row;
	public int previousColumn;
	public int previousRow;
	public int targetX;
	public int targetY;
	public bool isMatched = false;
	
	private Board board;
	private GameObject otherLetter;
	private Vector2 firstTouchPosition;
	private Vector2 finalTouchPosition;
	private Vector2 tempPosition;
	public float swipeAngle = 0;
	public float swipeResist = 1f;
	
	
    // Start is called before the first frame update
    void Start(){
        board = FindObjectOfType<Board>();
		
		//targetX = (int)transform.position.x;
		//targetY = (int)transform.position.y;
		//row = targetY;
		//column = targetX; 
		//previousRow = row;
		//previousColumn = column;
    }

    // Update is called once per frame
    void Update()
    {
		FindMatches();
		if(isMatched){
			SpriteRenderer mySprite = GetComponent<SpriteRenderer>();
			mySprite.color = new Color(0f, 0f,0f, .2f);
		}
		targetX = column;
		targetY = row;
		if (Mathf.Abs(targetX - transform.position.x)> .1){
			//Move Towards the target
			tempPosition = new Vector2(targetX, transform.position.y);
			transform.position = Vector2.Lerp(transform.position, tempPosition, .6f);
		if(board.allLetters[column, row] != this.gameObject){
		board.allLetters[column, row] = this.gameObject;
		}
		
		
		}else{
			//Directly setthe position
			tempPosition = new Vector2(targetX, transform.position.y);
			transform.position = tempPosition;
			
	}
	if (Mathf.Abs(targetY - transform.position.y)> .1){
			//Move Towards the target
			tempPosition = new Vector2(transform.position.x, targetY);
			transform.position = Vector2.Lerp(transform.position, tempPosition, .6f);
			if(board.allLetters[column, row]!= this.gameObject){
		board.allLetters[column,row] = this.gameObject;
			}
			
		}else{
			//Directly setthe position
			tempPosition = new Vector2(transform.position.x, targetY);
			transform.position = tempPosition;
	}
	}
	
	public IEnumerator CheckMoveCo(){
		yield return new WaitForSeconds(.5f);
		if(otherLetter != null){
			if(!isMatched && !otherLetter.GetComponent<Letter>().isMatched){
				otherLetter.GetComponent<Letter>().row = row;
				otherLetter.GetComponent<Letter>().column = column;
				row = previousRow;
				column = previousColumn;
				yield return new WaitForSeconds(.5f);
			board.currentState = GameState.move;
			}else{
			board.DestroyMatches();
			
	}
			otherLetter = null;
			
	}
	}
        private void OnMouseDown()
		{
			if(board.currentState == GameState.move)
			{
		firstTouchPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
		}
		}
		
		private void OnMouseUp()
		{
			if(board.currentState == GameState.move){
			finalTouchPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
		CalculateAngle();
		}else{
			board.currentState = GameState.move;
		}
		
    }
		
		
	void CalculateAngle(){
		if(Mathf.Abs(finalTouchPosition.y - firstTouchPosition.y) > swipeResist || Mathf.Abs(finalTouchPosition.x - firstTouchPosition.x) > swipeResist)
		{
		swipeAngle = Mathf.Atan2(finalTouchPosition.y - firstTouchPosition.y, finalTouchPosition.x - firstTouchPosition.x)* 180/ Mathf.PI;
		//Debug.Log(swipeAngle);
		MovePieces();
		board.currentState = GameState.wait;
		}
		}
		
	void MovePieces(){
	if (swipeAngle > -45 && swipeAngle <= 45 && column < board.width-1){
		//Right Swipe
		otherLetter = board.allLetters[column + 1, row];
		previousRow = row;
		previousColumn = column;
		otherLetter.GetComponent<Letter>().column -=1;
		column += 1;
	}else if (swipeAngle > 45 && swipeAngle <= 135 && row < board.height-1){
		//Up Swipe
		otherLetter = board.allLetters[column, row + 1];
		otherLetter.GetComponent<Letter>().row -=1;
		previousRow = row;
		previousColumn = column;
		row += 1;
	}else if ((swipeAngle > 135 || swipeAngle <= -135) && column > 0){
		//Left Swipe
		otherLetter = board.allLetters[column - 1, row];
		otherLetter.GetComponent<Letter>().column +=1;
		previousRow = row;
		previousColumn = column;
		column -= 1;
	}else if (swipeAngle < -45 && swipeAngle >= -135 && row > 0){
		//Down Swipe
		otherLetter = board.allLetters[column, row - 1];
		otherLetter.GetComponent<Letter>().row +=1;
		previousRow = row;
		previousColumn = column;
		row	-= 1;
		}
		StartCoroutine(CheckMoveCo());
}
    void FindMatches(){
	if(column > 0 && column < board.width - 1){
	GameObject leftLetter1 = board.allLetters[column - 1, row];
	GameObject rightLetter1 = board.allLetters[column + 1, row];
	if(leftLetter1 != null  &&  rightLetter1 != null){
		
	if (leftLetter1.tag == this.gameObject.tag && rightLetter1.tag == this.gameObject.tag){
		leftLetter1.GetComponent<Letter>().isMatched = true;
		rightLetter1.GetComponent<Letter>().isMatched = true;
		isMatched = true;
		}
	}
	}
	if(row > 0 && row < board.height - 1)
	{
	GameObject upLetter1 = board.allLetters[column, row + 1];
	GameObject downLetter1 = board.allLetters[column, row - 1];
	if(upLetter1 != null && downLetter1 != null)
	{
	if (upLetter1.tag == this.gameObject.tag  &&  downLetter1.tag == this.gameObject.tag){
		upLetter1.GetComponent<Letter>().isMatched = true;
		downLetter1.GetComponent<Letter>().isMatched = true;
		isMatched = true;
	}
}
	}	
}

}

  1. board
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum GameState{
	wait, 
	move
}


public class Board : MonoBehaviour
{
	public GameState currentState = GameState.move;
	public int width;
	public int height;
	public int offSet;
	public GameObject tilePrefab;
	public GameObject[] letters;
	private BackgroundTile[,] allTiles;
	public GameObject[,] allLetters;
	
    // Start is called before the first frame update
    void Start()
    {
       allTiles = new BackgroundTile[width, height]; 
	   allLetters = new GameObject[width, height];
	   SetUp();
    }

private void SetUp()
{
	for (int i = 0; i < width; i++)
	{
		for(int j = 0; j < height; j++){
			Vector2 tempPosition = new Vector2(i,j + offSet);
			GameObject backgroundTile = Instantiate(tilePrefab, tempPosition, Quaternion.identity) as GameObject;
			backgroundTile.transform.parent = this.transform;
			backgroundTile.name = "(" + i + ", " + j + ")";
			int letterToUse = Random.Range(0, letters.Length);
			int maxIterations = 0;
			while(MatchesAt(i,j,letters[letterToUse]) && maxIterations < 100){
				letterToUse = Random.Range(0, letters.Length);
				maxIterations++;
				Debug.Log(maxIterations);
			}
			maxIterations = 0;
			
			GameObject letter = Instantiate(letters[letterToUse], tempPosition, Quaternion.identity);
			letter.GetComponent<Letter>().row = j;
			letter.GetComponent<Letter>().column = i;
			letter.transform.parent = this.transform;
			letter.name = "(" + i + ", " + j + ")";
			allLetters[i,j] = letter;
		}
	}
}
private bool MatchesAt(int column, int row, GameObject piece){
	if(column > 1 && row > 1){
		if(allLetters[column -1, row].tag == piece.tag && allLetters[column -2, row].tag == piece.tag){
		return true;
		}
		if(allLetters[column, row -1].tag == piece.tag && allLetters[column, row -2].tag == piece.tag){
		return true;
		}
	}else if(column <= 1 || row <= 1){
		if(row > 1){
			if(allLetters[column, row - 1].tag == piece.tag && allLetters[column, row - 2].tag == piece.tag){
		return true;
		}
}



if(column > 1){
			if(allLetters[column -1,row].tag == piece.tag && allLetters[column - 2, row].tag == piece.tag){
		return true;
		}
}
}
	return false;
	
}

private void DestroyMatchesAt(int column, int row){
	if(allLetters[column, row].GetComponent<Letter>().isMatched){
		Destroy(allLetters[column, row]);
		allLetters[column, row] = null;
		
	}
	
}

public void DestroyMatches(){
	for(int i = 0; i < width; i++){
	for(int j = 0; j < height; j++){
	if(allLetters[i,j] != null){
		DestroyMatchesAt(i,j);
		
	}
	}
	}
	StartCoroutine(DecreaseRowCo());
}

	
private IEnumerator DecreaseRowCo(){
	int nullCount = 0;
	for(int i = 0; i < width; i ++){
		for(int j = 0; j < height; j ++){
			if(allLetters[i, j] == null){
				nullCount++;
			}else if(nullCount > 0){
				allLetters[i,j].GetComponent<Letter>().row -= nullCount;
				allLetters[i, j - nullCount] = allLetters[i, j];
				allLetters[i,j] = null;
			}
		}
		nullCount = 0;
	}
	yield return new WaitForSeconds(.4f);
	StartCoroutine(FillBoardCo());
}


 private void RefillBoard(){
        for (int i = 0; i < width; i ++){
            for (int j = 0; j < height; j ++){
                if(allLetters[i, j] == null){
                    Vector2 tempPosition = new Vector2(i, j + offSet);
                    int letterToUse = Random.Range(0, letters.Length);
                    GameObject piece = Instantiate(letters[letterToUse], tempPosition, Quaternion.identity);
                    allLetters[i, j] = piece;
                    piece.GetComponent<Letter>().row = j;
                    piece.GetComponent<Letter>().column = i;

                }
            }
        }
    }
	
	 private bool MatchesOnBoard(){
        for (int i = 0; i < width; i ++){
            for (int j = 0; j < height; j ++){
                if(allLetters[i, j]!= null){
                    if(allLetters[i, j].GetComponent<Letter>().isMatched){
                        return true;
                    }
                }
            }
        }
		return false;
	 }


 private IEnumerator FillBoardCo(){
        RefillBoard();
        yield return new WaitForSeconds(.5f);

        while(MatchesOnBoard()){
            yield return new WaitForSeconds(.5f);
            DestroyMatches();
        }
        yield return new WaitForSeconds (.5f);
		currentState = GameState.move;

    }
}

This sounds like basic pattern matching… and perhaps an exhaustive search?

If the pattern to be matched is A-B-C and it must be A-B-C, then you need to basically feed triplets of your board into a comparison function that detects A-B-C and returns false otherwise.

If it is like a recipe, eg, A, B and C simply have to be present, it’s pretty similar in that you feed triplets of your board into recipe matcher that simply “checks off” the presence of A, B, C separately and when done, returns true if all components were present.

You may wish to separate the match logic from the presentation logic above, so you don’t have to consider GameObjects and compare them in ways that may make setting up the recipes tricky.

Tile-based / grid-based 2D games: match3, tetris, chips challenge, rogue, etc:

For any tile-based game such as Match3 or Tetris or a grid-based Roguelike, do all the logical comparisons in your own data storage mechanism for the tiles, such as a 2D array of tiles.

Otherwise you needlessly bind your game logic into Unity objects and the Unity API, making it about 10x more complicated than it needs to be.

If you have no idea how to work with 2D arrays, hurry to some basic C# tutorials for the language portions of it, then look at any good tutorial that uses a 2D array

Here is my Match3 demo using this technique of storing data in a grid. Full source linked in game comments.

It stores all of its data in a 2D array:

PieceController[,] Board;

This allows for easy simple checking in code, not relying on anything like physics.

You should strive to use that pattern for all logic, then only use Unity to present what is happening in the game logic.

Thank you so much for your kind answer, it was really helpful.
Yes, unfortunately I have no idea how to make an array or anything, but now I know at least what I can look for and where to move. It seems to be less impossible than it was before - and it is a great step. Thank you for providing your project as well! I ll definitely check it.