Checking for adjacent gems of similar color in a grid like Bejeweled

Hi,

Can anyone tell me what is the most efficient way of implementing Bejeweled type logic for detecting three or more gems of the same color adjacent to one another horizontally and vertically?

Thanks.

The simplest way would be to do 4 Linecast or Raycast in those directions.

So I got to feeling a little frisky about it and wrote a simple set of functions that would check for gems near the one you are at. Then I thought, well, you would also need something to check all the connected gems. So I wrote that too.

var gemGrid=1.0;

function FindAllConnectedGems(startObject : GameObject) : Array{
	var Data : Array=new Array(startObject);
	var cont=true;
	for(var i=0; i<Data.Length; i++){
		var gems=CheckForGems(Data[data[i]);
		for(var j=0; j<gems.Length; j++){
			var found=false;
			for(var k=0; k<Data.Length; k++){
				if(gems[j]=Data[k]) found=true;
			}
			if(!found) Data.Add(gems[j]);
		}
	}
	return Data;
}

function CheckForGems(fromObject : GameObject) : Array{
	var retval : Array=new Array();
	CheckGem(fromObject, Vector3.up, retval);
	CheckGem(fromObject, Vector3.right, retval);
	CheckGem(fromObject, -Vector3.up, retval);
	CheckGem(fromObject, -Vector3.right, retval);
	return retval;
}

function CheckGem(fromObject : GameObject, direction : Vector3, array : Array){
	var hit : RaycastHit;
	var toPoint=fromObject.transform.position + direction * gemGrid;
	if(Physics.Linecast(fromObject.transform.position, toPoint, hit))
		AddGem(array, object);
}

function AddGem(array : Array, object : GameObject, tag : String){
	if(object.tag==tag) array.Add(object);
}

how do you position the jewels? If they are fixed positions in a grid like bejewled then just do a matrix lookup. Have a reference in a big matrix and just check the adjacent slots.

Thanks i will try it out and let you know if it works for me. Thanks for the extra effort u gave to write down the code for me. appreciate it.

@Todilo: Thats what i had in mind and i was trying that also but in my game, the jewels will be changing their positions. I am also updating their position accordingly in a matrix. But sometimes more than three jewels can come together. I want to check this. I want to something like combo moves where all adjacent color jewel are deleted. Player needs to maximize is score by arranging maximum jewels in one move.

You could add an additional check to your code after you knew there were three jewels and so a deletion was going to happen. Just check each jewel for additional adjacent jewels of the same color but only one step away. If a jewel of the correct color is found, add that to the bottom of the list and check it later for adjacent jewels.

So, in a situation where your board looked like this:

3 + + + +
2 1 + + +

  • x x x +

If the three “x” trigger a deletion, checking the leftmost x will find 1. Checking 1 will find 2. Checking 2 will find 3.

You will have to deal with the complication of not wasting cycles by checking the same spot on the grid twice. This is also important because you don’t want to add the same jewel multiple times into the list of jewels you are checking. This could create an infinite loop.

In (rather clunky) pseudocode:

LIST = Have a list of jewels that are going to be deleted.
ALREADY_CHECKED = list we can add checked spots to.  It should start as LIST.

While not at end of LIST
   If up exists and is not in ALREADY_CHECKED, CheckIt().
   If down exists and is not in ALREADY_CHECKED, CheckIt().
   If right exists and is not in ALREADY_CHECKED, CheckIt().
   If left exists and is not in ALREADY_CHECKED, CheckIt().
Repeat while.
Delete everything in IT.
Go on to code for what happens next (falling jewels or whatever happens).

CheckIt(IT)
  Add IT to ALREADY_CHECKED.
  If IT is the right color, add IT to LIST.

If the game is strictly grid-based, you don’t need to use raycasts or anything like that; just perform the checks directly as mentioned above.