Colour Matching Game: Search board for matches?

Hi,
I’m trying to make a game similar to the likes of Puyo Puyo, where the player controls falling puzzle pieces of different colours and has to put them in groups of 4. I’ve managed to get most of the game working so far, but I’m struggling with searching to board to find matches.

At the minute each individual puzzle block has 4 colliders on each side to see if theirs a match to the immediate side of it, and if their is, it puts it in a list on that gameobject. My basic idea was that the script attached to the board would look at all the puzzle pieces (stored in a list on that script) and would look at that puzzle piece’s match list and add the length of that list to a int. It would then look at the lists of the puzzle pieces in the first puzzle piece’s match list and add that to the int, and would keep doing that until all the puzzle pieces in that group are accounted for. If their is more than 4 pieces in that group, they would all be destroyed.

My problem is that I can’t formulate that idea into a piece of code that works. It either doesn’t work at all, or works in a way it’s not supposed to. Below is my 3rd or 4th re-write of this code which, whilst doesn’t pull up any errors, doesn’t seem to do anything. I was wondering if someone could point me in the right direction or tell me a better way of doing this.

	   public void NextMove()
       {
        // check matches
        foreach (PuyoPuyo puyo in puyosOnBoard)
        {
            CheckPuyo(puyo);
        }


        //check rubbish

        next.AddPuyo();
    }


    void CheckPuyo(PuyoPuyo puyo)
    {
        int matchNumb = 0;
        if(puyo.matchedPuyos != null)
        {
            matchNumb += puyo.matchedPuyos.Count;

            if (puyo.matchedPuyos != null)
            {
                foreach (PuyoPuyo p in puyo.matchedPuyos)
                {
                    Debug.Log("2.2");
                    if (p.matchedPuyos.Count > 0)
                    {
                        Debug.Log("3");
                        CheckPuyo2(p, matchNumb, puyo);
                    }
                }
            }
        }
    }

    void CheckPuyo2(PuyoPuyo puyo, int matchNumb, PuyoPuyo originalPuyo)
    {
        matchNumb += puyo.matchedPuyos.Count - 1;
        foreach (PuyoPuyo p in puyo.matchedPuyos)
        {
            if (p.matchedPuyos.Count > 1)
            {
                CheckPuyo2(p, matchNumb, originalPuyo);
            }
            else
            {
                if(matchNumb >= 4)
                {
                    Destroy(originalPuyo.gameObject);
                }
            }
        }


    }

Thanks

i think what you are missing is a flood fill algorithm similar to what you see in a paint program.
how it works is starting with a list with one coordinate, add all the surrounding matches to the list
and marking the checked squares as closed so they can only be checked once.
you keep doing this till the list is empty.

to make your algo more simple i would recommend marking everything on a 2D grid instead of marking connections on a list of game objects. you could move through your connections in a similar way like you describe as “nodes” but the 2d grid way is simpler and keep you more organized for other things too.

Anyways, here is a flood algo example that counts how many similar squares are touching a coordinate on a grid. hopefully it gets you started in the right direction:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class findmatch : MonoBehaviour {
	public class two
		{ 
		public int x,y;
		public two(int X,int Y){
			x = X;y=Y;
		}
	}
	public int[,] grid = new int[10,10];
	
	public two[] cross = new two[4]{new two(1,0),new two(-1,0),new two(0,-1),new two(0,1)};

	void Start () {

		grid [2, 2] = 5;
		grid [2, 3] = 5;
		grid [2, 4] = 5;
		grid [1, 4] = 5;

		grid [8, 2] = 2;
		grid [8, 3] = 2;
		grid [8, 4] = 2;

		print ("Connections to square 2 4 =" + flood (2, 4));
		print ("Connections to square 8 2 =" + flood (8, 2));
	}


	int flood(int X, int Y){
		two q = new two (X, Y);
		int type = grid [q.x, q.y];
		int ret = 0;
		List <two> a = new List<two>();
		a.Add (q);
		bool[,] closed = new bool[10, 10];
		closed [q.x,q.y] = true;
		while (a.Count>0) {
			int i = cross.Length;
			while(i>0){i--;
				two check = new two(a[0].x+cross_.x,a[0].y+cross*.y);*_

* if(check.x>- 1&&check.y>-1&&check.x<10&&check.y<10){*
* if(closed[check.x,check.y]==false){*
* closed[check.x,check.y]=true;*
* if(grid[check.x,check.y] == type){*
* a.Add(check);*
* ret++;*
* }}}*
* }*
* a.RemoveAt(0);}*

* return ret;*
* }*

}
if you want to scan your entire board for matches just loop through all the coordinates to see if each of there fill() is larger than whatever number you want

In most of these games, the matches fuse together once the new piece ‘drops’ into place.

This builds a very simple grid of pieces that you can store in an array. For example, if your board was 10 pieces across and 20 pieces high, you could make an array of 10x20 ints (or a single array of 200 ints) and start them all at ‘0’, then fill them with ‘1’ when a blue piece fits into place, ‘2’ when a green one, ‘3’ for a yellow one etc.

If you’ve got an array like this, it’s quite simple to figure out if you have colour matches.


Start by making a new 10x20 or 200-index array of bools to store if pieces have already been checked, then begin in the lower-left corner and work your way up.

So for each combination of ‘x’ (horizontal) and ‘y’ (vertical) in your grid, you check to see if you’ve already processed it, and if not you create a list to keep the matches in, and then begin to recursively look for matching coloured squares in your grid. For each neighbour, you check that…

a) Have not been checked yet, and

b) Have the same colour as the first point you found.

If they are the same colour, add them to the list of matches and then for each of the neighbours you call the same function again. This will spread out till you’ve found all the neighbouring items of the same colour.


Then you can update the piece meshes so that they look like they are one piece and check the total number of matches you found - if it’s more than your threshold, make it ‘pop’.

Continue until you’ve checked every point in the array - after a while you’ll end up reaching the top of your pile when you’ve got a whole row of just zeroes. You can stop there.