Hello all,
I wanted to post my code that I have written for checking the running color matches of 3 or more in a straight line, and I also want to include my Resettle Board method also. My Horz, Vert, and Diag match checking seems to be working correctly. I have called each directional check method by itself (and I still am just for testing) and tested it visually, and made sure it was doing what it was supposed to on the grid behind the scenes. I left the gaps on the grid visually and empty on the grid board so I could make sure that my match routine was matching directions, color, and basically doing whats its supposed to be, and doing it correctly, LoL. Have you ever added like 100 print statements after each line of your code to âtellâ you in the console whats actually going on vs. what you THOUGHT was happenning? NevermindâŚ(Grin) anyways, If you folks could just skim over my methods here and make sure I have written what we have discussed so far correctly, I will get to my point:
The matches seem to be correct when I call each method one after the other as my CheckForMatch method shows, or If I were (and will) add them all together so its one big â8 direction Check methodâ it still works fine. I have checked this again, Visually, and In memory (printed to console what was at location âx,yâ from the 2D grid after visual blocks are destroyed at same location)
The problem seems to be SOMETIMES, AFTER I haved called the directional check, it finds matches, destroys them,THEN resettles the board⌠after resettling, the check for match is called again, THEN it seems to find matches that are not color related, or in line with whatever portion of the check routine was running (i.e it was searching up and to the left, and found matches, destroys the correct matches, but also will seem to destory some random block that was not âin lineâ with the direction it was giong!)
Can anyone see any obvious mistakes that I dont here? I am happy to post other code if needed or explain further if needed.
As always, you guys have been a great help, THANKS
King
Edit: Uploaded two picturesâŚ
Here is the BEFORE and AFTER of the grid. The three black dots just indicate the source of the check, the yellow gem on the bottom is the START gem of recursion.
NOTICE it did NOT register any of the matches but the ones going LEFT. wtf?!
CheckForMatch:
// **CHECKING FOR MATCHING GEMS OF 3 OR MORE**
public static void CheckForMatch(GameBoard board)
{
//Start with the 1st tile in the list of Base Tiles
for(int i = 0;i < topOfRecursionBaseTiles.Count;i++)
{
//End list that will contain all matches of 3 or more found in match 3 pass
finalListOfGemsToDestroy.Clear();
//Make a Copy of 2D gridboard of Type "Gem" for Manipulation purposes
GameBoard.CopyGridBoard(board, CoreGameManager.gridBoardCopy);
//Iterate the List of Parent/Master Base Tiles
parentBaseTile = topOfRecursionBaseTiles[i];
//Call each matchmaking method seperatly for now, we will combine all dir checking together after testing...
horzMatchCount = 0;
collector.Clear ();
CheckForNeighborsHorz(parentBaseTile,parentBaseTile.Row,parentBaseTile.Column);
vertMatchCount = 0;
collector.Clear ();
CheckForNeighborsVert(parentBaseTile,parentBaseTile.Row,parentBaseTile.Column);
diagzMatchCount = 0;
collector.Clear ();
CheckForNeighborsDiagz(parentBaseTile,parentBaseTile.Row,parentBaseTile.Column);
//If there were any set of 3 matches or more found, then go destroy gems, resettle board, check for matches again...
if(finalListOfGemsToDestroy.Count >= minNumGemsForChain)
{
//Destroy all VISUAL game objects in the FINAL LIST of Gems to remove off the VisualGrid
DestroyMatchingGems(finalListOfGemsToDestroy);
//We removed gems from the grid, now FILL in the gaps left behind, and add NEW PARENT tiles that were found above the empty gaps,as the gapfill may possibly have caused more matches
SettleBlocks(CoreGameManager.gridBoard);
//The resettle of the board may have caused NEW matches, go check our ParentTile list again until no more base tiles are found
CheckForMatch(CoreGameManager.gridBoard);
}
}
Directional Checks:
//Check for same color tiles in a STRAIGHT line of 3 or more HORIZONTALLY
public static void CheckForNeighborsHorz(Gem currentBaseTile, int x, int y)
{
/******************************************************
* If this function finds that the cell is NULL, then we skip tile. (Null = Already Tested this Tile)
* If this function finds that the cell is EMPTY, then we skip tile.(Empty = its..EMPTY... dont need to test)
* parentBaseTile is STATIC and holds the ORIGINAL base tile this check started from and is only changed to a new root gem by CheckForMatch()
******************************************************/
//Horz Checks:
//Check LEFT, Make sure we are inside the board boundry and the tile we are looking at is NOT NULL, and NOT EMPTY
if(x - 1 >= 0 && CoreGameManager.gridBoardCopy[x-1,y] != null && CoreGameManager.gridBoardCopy[x-1,y].GemColorType != Gem.GEMTYPE.EMPTY)
{
isCheckingNeighbors = true;
while (isCheckingNeighbors)
{
//Since we will be LOOPING our check to the left we want to make sure we AGAIN are in bounds of the grid...etc.etc.
if(x - 1 >= 0 && CoreGameManager.gridBoardCopy[x-1,y] != null && CoreGameManager.gridBoardCopy[x-1,y].GemColorType != Gem.GEMTYPE.EMPTY )
{
//Test the tile to see if colors match
TestTile(x-1,y);
//If colors DO MATCH
if(isGemMatching == true)
{
//Add it to Temp list to track all the same color gems that are in the SAME DIRECTION (e.g All gems found to the LEFT of the Root gem)
collector.Add(CoreGameManager.gridBoardCopy[x-1,y]);
//Make the tile (to the left in this case) that was just checked AND MATCHED, our NEW PARENT tile to check from
currentBaseTile = CoreGameManager.gridBoardCopy[x-1,y];
//Make tile NULL as we have checked this tile...and our parent tile null as we are using it to check from and we dont want to check any tile twice?
CoreGameManager.gridBoardCopy[x-1,y] = null;
CoreGameManager.gridBoardCopy[x,y] = null;
//Increment the Horz Match Counter (for later use?)
horzMatchCount ++;
x = x-1;
//y stays the same, we are HORZ checking
}
else
//The gems do NOT MATCH
{
isCheckingNeighbors = false;//Set the LOOP Exit condition.
}
}
else
//tile is EMPTY, or we are OFF the edge of the grid so no need to check further, kill loop.
{
isCheckingNeighbors = false;
}
}
//Put ROOT tile back, Start check to RIGHT FROM the ROOT tile that we started checking left from....
currentBaseTile = parentBaseTile;
x = currentBaseTile.Row;
y = currentBaseTile.Column;
}
//CHECKING RIGHT....
if(x + 1 <= GameBoard.BoardWidth-1 && CoreGameManager.gridBoardCopy[x+1,y] != null && CoreGameManager.gridBoardCopy[x+1,y].GemColorType != Gem.GEMTYPE.EMPTY)
{
isCheckingNeighbors = true;
while (isCheckingNeighbors)
{
if(x + 1 <= GameBoard.BoardWidth-1 && CoreGameManager.gridBoardCopy[x+1,y] != null && CoreGameManager.gridBoardCopy[x+1,y].GemColorType != Gem.GEMTYPE.EMPTY )
{
TestTile(x+1,y);
if(isGemMatching == true)
{
collector.Add(CoreGameManager.gridBoardCopy[x+1,y]);
currentBaseTile = CoreGameManager.gridBoardCopy[x+1,y];
//Make block NULL as we have checked this block...and our parent block null as we are using it to check from and we dont want to check it twice.
CoreGameManager.gridBoardCopy[x+1,y] = null;
CoreGameManager.gridBoardCopy[x,y] = null;
x = x+1;
//y stays the same, we are HORZ checking
horzMatchCount++;
}
else
{
isCheckingNeighbors = false;//Set the LOOP Exit condition.
}
}
else
{
isCheckingNeighbors = false;
}
}
currentBaseTile = parentBaseTile;
x = currentBaseTile.Row;
y = currentBaseTile.Column;
}
horzMatchCount = 0;
//If we Found 3 or more of same color tile in a straight line (horz in this case) then, Process collector
if(collector.Count >= minNumGemsForChain - 1)
{
//If the final list already has the ROOT gem in it, then DONT add the base gem to the list....
if(!finalListOfGemsToDestroy.Contains(parentBaseTile))
{
finalListOfGemsToDestroy.Add (parentBaseTile);
}
//There were 3 or more gems of same color found in a row on the same line, add ALL gems to final list of Gems to Destroy
finalListOfGemsToDestroy.AddRange(collector);
}
}
//Check for same color tiles in a STRAIGHT line of 3 or more VERTICALLY
public static void CheckForNeighborsVert(Gem currentBaseTile, int x, int y)
{
//Vert Checks:
//UP
if(y + 1 <= GameBoard.BoardHeight-1 && CoreGameManager.gridBoardCopy[x,y+1] != null && CoreGameManager.gridBoardCopy[x,y+1].GemColorType != Gem.GEMTYPE.EMPTY)
{
isCheckingNeighbors = true;
while (isCheckingNeighbors)
{
if(y+1 <= GameBoard.BoardHeight-1 && CoreGameManager.gridBoardCopy[x,y+1] != null && CoreGameManager.gridBoardCopy[x,y+1].GemColorType != Gem.GEMTYPE.EMPTY )
{
TestTile(x,y+1);
if(isGemMatching == true)
{
collector.Add(CoreGameManager.gridBoardCopy[x,y+1]);
currentBaseTile = CoreGameManager.gridBoardCopy[x,y+1];
CoreGameManager.gridBoardCopy[x,y+1] = null;
CoreGameManager.gridBoardCopy[x,y] = null;
vertMatchCount++;
//x stays the same, we are VERT checking
y = y+1;
}
else
{
isCheckingNeighbors = false;//Set the LOOP Exit condition.
}
}
else
{
isCheckingNeighbors = false;
}
}
currentBaseTile = parentBaseTile;
x = currentBaseTile.Row;
y = currentBaseTile.Column;
}
//DOWN
if(y - 1 >= 0)
{
isCheckingNeighbors = true;
while (isCheckingNeighbors)
{
if(y - 1 >= 0 && CoreGameManager.gridBoardCopy[x,y-1] != null && CoreGameManager.gridBoardCopy[x,y-1].GemColorType != Gem.GEMTYPE.EMPTY )
{
TestTile(x,y-1);
if(isGemMatching == true)
{
collector.Add(CoreGameManager.gridBoardCopy[x,y-1]);
currentBaseTile = CoreGameManager.gridBoardCopy[x,y-1];
CoreGameManager.gridBoardCopy[x,y-1] = null;
CoreGameManager.gridBoardCopy[x,y] = null;
//x stays the same, we are VERT checking
y = y-1;
vertMatchCount++;
}
else
{
isCheckingNeighbors = false;//Set the LOOP Exit condition.
}
}
else
{
isCheckingNeighbors = false;
}
}
currentBaseTile = parentBaseTile;
x = currentBaseTile.Row;
y = currentBaseTile.Column;
}
vertMatchCount = 0;
if(collector.Count >= minNumGemsForChain - 1)
{
if(!finalListOfGemsToDestroy.Contains(parentBaseTile))
{
finalListOfGemsToDestroy.Add (parentBaseTile);
}
finalListOfGemsToDestroy.AddRange(collector);
}
}
//Check for same color tiles in a STRAIGHT line of 3 or more DIAGONALLY(any of the 4 dir's)
public static void CheckForNeighborsDiagz(Gem currentBaseTile, int x, int y)
{
//Diagz Checks:
//CHECKING LEFT and DOWN...
if(x - 1 >= 0 && y-1 >= 0 && CoreGameManager.gridBoardCopy[x-1,y-1] != null && CoreGameManager.gridBoardCopy[x-1,y-1].GemColorType != Gem.GEMTYPE.EMPTY)
{
isCheckingNeighbors = true;
while (isCheckingNeighbors)
{
if(x - 1 >= 0 && y-1 >= 0 && CoreGameManager.gridBoardCopy[x-1,y-1] != null && CoreGameManager.gridBoardCopy[x-1,y-1].GemColorType != Gem.GEMTYPE.EMPTY )
{
TestTile(x-1,y-1);
if(isGemMatching == true)
{
collector.Add(CoreGameManager.gridBoardCopy[x-1,y-1]);
currentBaseTile = CoreGameManager.gridBoardCopy[x-1,y-1];
CoreGameManager.gridBoardCopy[x-1,y-1] = null;
CoreGameManager.gridBoardCopy[x,y] = null;
diagzMatchCount ++;
x = x-1;
y = y-1;
}
else
{
isCheckingNeighbors = false;//Set the LOOP Exit condition.
}
}
else
{
isCheckingNeighbors = false;
}
}
currentBaseTile = parentBaseTile;
x = currentBaseTile.Row;
y = currentBaseTile.Column;
}
//CHECKING RIGHT and UP....
if(x + 1 <= GameBoard.BoardWidth-1 && y+1 <= GameBoard.BoardHeight-1 && CoreGameManager.gridBoardCopy[x+1,y+1] != null && CoreGameManager.gridBoardCopy[x+1,y+1].GemColorType != Gem.GEMTYPE.EMPTY )
{
isCheckingNeighbors = true;
while (isCheckingNeighbors)
{
if(x + 1 <= GameBoard.BoardWidth-1 && y+1 <= GameBoard.BoardHeight-1 && CoreGameManager.gridBoardCopy[x+1,y+1] != null && CoreGameManager.gridBoardCopy[x+1,y+1].GemColorType != Gem.GEMTYPE.EMPTY )
{
TestTile(x+1,y+1);
if(isGemMatching == true)
{
collector.Add(CoreGameManager.gridBoardCopy[x+1,y+1]);
currentBaseTile = CoreGameManager.gridBoardCopy[x+1,y+1];
CoreGameManager.gridBoardCopy[x+1,y+1] = null;
CoreGameManager.gridBoardCopy[x,y] = null;
x = x+1;
y = y+1;
diagzMatchCount++;
}
else
{
isCheckingNeighbors = false;//Set the LOOP Exit condition.
}
}
else
{
isCheckingNeighbors = false;
}
}
currentBaseTile = parentBaseTile;
x = currentBaseTile.Row;
y = currentBaseTile.Column;
}
diagzMatchCount = 0;
//If we Found 3 or more of same color tile in a straight line then, Process collector
if(collector.Count >= minNumGemsForChain - 1)
{
if(!finalListOfGemsToDestroy.Contains(parentBaseTile))
{
finalListOfGemsToDestroy.Add (parentBaseTile);
}
finalListOfGemsToDestroy.AddRange(collector);
}
collector.Clear();
//CHECKING LEFT and UP
if(x - 1 >= 0 && y+1 <= GameBoard.BoardHeight-1 && CoreGameManager.gridBoardCopy[x-1,y+1] != null && CoreGameManager.gridBoardCopy[x-1,y+1].GemColorType != Gem.GEMTYPE.EMPTY)
{
isCheckingNeighbors = true;
while (isCheckingNeighbors)
{
if(x - 1 >= 0 && y+1 <= GameBoard.BoardHeight-1 && CoreGameManager.gridBoardCopy[x-1,y+1] != null && CoreGameManager.gridBoardCopy[x-1,y+1].GemColorType != Gem.GEMTYPE.EMPTY )
{
TestTile(x-1,y+1);
if(isGemMatching == true)
{
collector.Add(CoreGameManager.gridBoardCopy[x-1,y+1]);
currentBaseTile = CoreGameManager.gridBoardCopy[x-1,y+1];
CoreGameManager.gridBoardCopy[x-1,y+1] = null;
CoreGameManager.gridBoardCopy[x,y] = null;
diagzMatchCount ++;
x = x-1;
y = y+1;
}
else
{
isCheckingNeighbors = false;//Set the LOOP Exit condition.
}
}
else
{
isCheckingNeighbors = false;
}
}
currentBaseTile = parentBaseTile;
x = currentBaseTile.Row;
y = currentBaseTile.Column;
}
//CHECKING RIGHT and DOWN....
if(x + 1 <= GameBoard.BoardWidth-1 && y-1 >= 0 && CoreGameManager.gridBoardCopy[x+1,y-1] != null && CoreGameManager.gridBoardCopy[x+1,y-1].GemColorType != Gem.GEMTYPE.EMPTY)
{
isCheckingNeighbors = true;
while (isCheckingNeighbors)
{
if(x + 1 <= GameBoard.BoardWidth-1 && y-1 >= 0 && CoreGameManager.gridBoardCopy[x+1,y-1] != null && CoreGameManager.gridBoardCopy[x+1,y-1].GemColorType != Gem.GEMTYPE.EMPTY )
{
TestTile(x+1,y-1);
if(isGemMatching == true)
{
collector.Add(CoreGameManager.gridBoardCopy[x+1,y-1]);
currentBaseTile = CoreGameManager.gridBoardCopy[x+1,y-1];
CoreGameManager.gridBoardCopy[x+1,y-1] = null;
CoreGameManager.gridBoardCopy[x,y] = null;
x = x+1;
y = y-1;
diagzMatchCount++;
}
else
{
isCheckingNeighbors = false;//Set the LOOP Exit condition.
}
}
else
{
isCheckingNeighbors = false;
}
}
currentBaseTile = parentBaseTile;
x = currentBaseTile.Row;
y = currentBaseTile.Column;
}
diagzMatchCount = 0;
//If we Found 3 or more of same color tile in a straight line ,rocess collector
if(collector.Count >= minNumGemsForChain - 1)
{
if(!finalListOfGemsToDestroy.Contains(parentBaseTile))
{
finalListOfGemsToDestroy.Add (parentBaseTile);
}
finalListOfGemsToDestroy.AddRange(collector);
}
collector.Clear ();
}
DESTROY FINAL LIST:
//Destroy FINAL list of contiguous matching gems. Send the LIST to destroy INTO the helper method
public static void DestroyMatchingGems(List<Gem> matchingListOfContiguousGemsToRemove)
{
//Go through each gem in our Final compiled list of gems to be destroyed
for(int i=0; i < matchingListOfContiguousGemsToRemove.Count;i++)
{
int x = matchingListOfContiguousGemsToRemove[i].Row;
int y = matchingListOfContiguousGemsToRemove[i].Column;
Destroy (CoreGameManager.visualGrid[x,y]);
//Populate gridtile with a NEW EMPTY, NORMAL GEM
CoreGameManager.gridBoard[x,y] = new Gem(Gem.GEMTYPE.EMPTY,Gem.GEMMOD.NORMAL,x,y);
//Visual Grid array NULL is "empty"
CoreGameManager.visualGrid[x,y] = null;
}
//Clean Up
matchingListOfContiguousGemsToRemove.Clear();
}
RESETTLE BOARD:
/*
* In each row, weâll work our way up from the bottom until we find an empty cell.
* Then, weâll make a note of that cell. The next time we find a tile,
* weâll simply shift it down to that location and add one to our âempty cellâ index:
*/
public static void SettleBlocks(GameBoard board)
{
//Clear the List as we are about to use/re-use it
topOfRecursionBaseTiles.Clear ();
for (int x = 0; x < GameBoard.BoardWidth; x++)
{
firstEmptyTile = null;
for (int y = 0; y <GameBoard.BoardHeight; y++)
{
//check if the tile is EMPTY and firstEmptyTile is NULL
if(board[x,y].GemColorType == Gem.GEMTYPE.EMPTY && !firstEmptyTile.HasValue )
{
firstEmptyTile = y;
}
else if(board[x,y].GemColorType != Gem.GEMTYPE.EMPTY && firstEmptyTile.HasValue)
{
CoreGameManager.visualGrid[x,firstEmptyTile.Value] = CoreGameManager.visualGrid[x,y];
board[x,firstEmptyTile.Value] = board[x, y];
board[x, y] = new Gem (Gem.GEMTYPE.EMPTY,Gem.GEMMOD.NORMAL,x,y);
//UPDATE INDEX POINTER COORDS IN THE "GEM" at BOARD LOCATION
//X will always be the same as we dont move Gems left to right when we resettle the board
board[x, firstEmptyTile.Value].Row = x;
//Y Needs to be updated as we moved it DOWN "firstEmptyTile.Value" number of squares
board[x, firstEmptyTile.Value].Column = firstEmptyTile.Value;//the NEW Y pos
//Add the gems ABOVE the empty gaps as ROOT base tiles since we updated their positions internally correctly
topOfRecursionBaseTiles.Add(board[x, firstEmptyTile.Value]);
//Get the current x,y transform (of the gem GAMEOBJECT) so we can change it
Vector3 currentGemToRestack = CoreGameManager.visualGrid[x,firstEmptyTile.Value].transform.position;
//Save the Value as the "New" Y position to use
currentGemToRestack.y = (firstEmptyTile.Value);
//Move the gem down
CoreGameManager.visualGrid[x,firstEmptyTile.Value].transform.position = currentGemToRestack;
//We moved the gem down, now make sure the empty gap index is updated
firstEmptyTile++;
//Make the x,y gamebject in memory NULL as we moved it (null is "empty" in the visualGrid Array of GameObjects)
CoreGameManager.visualGrid[x,y] = null;
}
}
}
//Testing
for(int i =0;i <topOfRecursionBaseTiles.Count;i++)
{
print ("topOfRecursionBaseTiles: "+topOfRecursionBaseTiles[i]);
}
}
Sorry for the LONG post, but I figured I would post the code BEFORE someone says âhey, we dont know what the hell your talking about without seeing itâŚâ Lol