r/Unity2D•
shaksta4

Help with Match 3 code logic

Question

Hey guys i've been racking my head through this for the past few hours, not really getting it. Hoping someone can help me out and point out where my mistake is.

Basically i'm trying to make a match 3 game. I've gotten to the point where I need to check the board if there are 3 or more tiles of the same value in a row. I've got a different array for each row and column of the board so now it's just up to looking through the arrays for 3 or more in a row.

Here's the code. It sometimes returns 3 in a row, almost always adds 2 in a row, and i've rare seen it add 4 in a row, although its rare to get four in a row when randomly generating my board in the first place.

List<Tile> ListOfSet = new List<Tile>();

    int ValueToCompare = 0;
    for (int i = 0; i < myList.Count - 1; i++)
    {
        ValueToCompare = myList[i].tile.value;

        if (myList[i + 1].tile.value == ValueToCompare)
        {
            ListOfSet.Add(myList[i + 1].tile);
            if (!ListOfSet.Contains(myList[i].tile))
            {
                ListOfSet.Add(myList[i].tile);
            }
        }
    }

    if(ListOfSet.Count <= 2)
    {
        ListOfSet.Clear();
    }
    else
    {
        MatchingSet.AddRange(ListOfSet);
        ListOfMatchingSets.Add(ListOfSet);
        print("There was a set found!!");
        //print("There is a set starting from: " + MatchingSet[0].transform.localPosition + " Ending at: " + myList[MatchingSet.Count-1].transform.localPosition);
    }       

MatchingSet is just a debug set I've got so I can see all the different "Matches" my code brings out. I add the "ListOfSet" To a list of lists so I can have access to each separate case of a match.

Please help!! Thanks

Posted Feb 25, 2019, 10:39 AM UTC

26
nicloay•

On my current job, I have a test task to write a match 3 game.

https://github.com/nicloay/Match3TestTask/blob/master/Assets/Scripts/Logic/MatchFinder/LineMatcher.cs

  • line 35 find hints
  • line 70 check is there a match at specific position

​

http://nicloay.com/Match3TestTask/ here is a webgl demo with autoplay button (basically get hint and make the move)

​

1
MBlueD•

(Assuming myList is an array containing the tiles in a row and ListOfSet contains the tiles in a single match)

First, it seems that the loop you are executing is not correct. You are going through the entire row and adding any sequence of two or more identical tiles to ListOfSet. That means that if a row has RRGBB (imagine each letter is a tile) your set will include RRBB as a match and as such will clear your <= 2 test and display what it found as a correct match, which is not what you want.

Consider using something like this (psuedocodish. Might need a bit of tweaking.):

int offset = 0;
int matchLength = 0;
List matches; // Stores all matches
Vector2 matchRange;  // Stores a match as a beginning and end index in the row
Tile t = null;
for (int i = 0; i < rowLength; i = i + offset) {
	t = row[i];
	for (offset = 1; offset + i < rowLength; offset++) {
		// The following check will keep the loop running until the we find a non-matching tile or find the end of the row, at which point offset is the length of the match
		if (t != row[i+offset] || i + offset + 1 == rowLength) {
			if (offset > 3) {
				// valid match 
				matchRange = new Vector2(i, i+offset - 1);
				matches.add(matchRange);
				break; // return to the main loop
			}
		}
	}
	
	// Loop again to find another match. the i+offset counter increment is setup so that we start from the next different tile in the row (the one that didn't match).
}

Check out the tutorial series by Mister Taft Creats. I haven't done this particular one but going by his other content this is bound to be very good for you.

1
shaksta4OP•

Thanks for your help. And you're right about the issue I'm facing. I'm following along what everything does with a pen and paper and the only case i didnt test for was if multiple doubles were in a row. So thanks for that.

I tried adapting your recommendation to my code but it's not giving me any meaningful data. There might be something wrong with it.

From what I understand, a case that is not handled is if the pair of 3 or more is found towards the end of the list, i.e. [RGBBBB]. It compares R with G, offset being 1. Says it's not equal, but since offset isn't > 3, it just starts the next iteration, incrementing offset and comparing R with B which again, is not equal. And it will just increment offset by 1 and start the next one.

Thoughts?

1
MBlueD•

Ah yes - the break should be in the outer if statement that checks the tile, something like this:

if (t != row[i+offset] || i + offset + 1 == rowLength) {
        if (offset > 3) {
            // valid match 
            matchRange = new Vector2(i, i+offset - 1);
            matches.add(matchRange);
        }
        break; // return to the main loop
}

This ought to fix the loop. Sorry about that.

EDIT: And another mistake - the test should be offset > 2 (or offset >= 3, whichever you prefer).

1
shaksta4OP•

Okay, data being returned finally looks kinda meaningful. There still is an error somewhere. It sometimes returns the start and end of a matching set, but sometimes it completely misses a set of 3, and other times it still returns a set of 2.

It also recognised a 4 in a row as 3 in a row.

At this point I feel like i gotta take a step back and maybe instead of returning the entire row and column as separate arrays, do something else to find 3 in a row. Possibly a recursive function that just checks each tile's neighbour or something. I didn't think it'd be this mentally taxing to find consecutive elements of the same value in an array.

1
MBlueD•

Recognizing 4 as 3 might be caused by the vector creation line:

matchRange = new Vector2(i, i+offset - 1);

Should probably be changed to

matchRange = new Vector2(i, i+offset);

Not sure about the other cases - examples would help.

This was napkin-code level and I basically just focused on getting the idea right. It should be easy to fix any mistakes if you trace the cases either by hand or through sprinkling some logs.

Check out the tutorial link I sent earlier. It's great and is surely going to be of help.

1