Skip to main content

Match 3 game - Check for matches

I'm out of ideas and need help. So far I generate a board nicely using a flood fill algorithm and a 2d-array, I can also move tiles around the board.

Each Tile knows its own row, column and ID (images get set depending on ID, it's also what I use to check for matches).

The version I have for checking matches right now almost works, but it does not remove Tiles correctly if the match happens on row/col that got changed because of the recent move (tiles above that move down because of the match that was made from my move).

I have a lot of code but Ill try to explain it:

I check for matches in my game loop, so each frame I loop through the 8x8 board and check for matches. To check for matches I have these methods:

private void checkIfUpMatch(int row, int col){ //recursive Tile toCheck = array[row][col]; toCheck.setChecked(true); //we set the tile as checked if(toCheck.getRow() >= 7){ //if next row doesnt exist return; } if(array[row + 1][col].getId() == array[row][col].getId()) { verticalMatches ++; checkIfUpMatch((toCheck.getRow() + 1), toCheck.getCol()); } return; } private void checkIfDownMatch(int row, int col){ //recursive Tile toCheck = array[row][col]; toCheck.setChecked(true); if(toCheck.getRow() <= 0){ //if next row doesnt exist return; } if(array[row - 1][col].getId() == array[row][col].getId()) { verticalMatches ++; checkIfDownMatch((toCheck.getRow() - 1), toCheck.getCol()); } return; } private void checkIfLeftMatch(int row, int col){ //recursive Tile toCheck = array[row][col]; toCheck.setChecked(true); if(toCheck.getCol() <= 0){ //if next col doesnt exist return; } if(array[row][col - 1].getId() == array[row][col].getId()) { horizontalMatches ++; checkIfLeftMatch((toCheck.getRow()), toCheck.getCol() - 1); } return; } private void checkIfRightMatch(int row, int col){ //recursive Tile toCheck = array[row][col]; toCheck.setChecked(true); if(toCheck.getCol() >= 7){ //if next col doesnt exist return; } if(array[row][col + 1].getId() == array[row][col].getId()){ horizontalMatches ++; checkIfRightMatch((toCheck.getRow()), toCheck.getCol() + 1); } return; } 

All of these methods do the same thing, just for up/down/left/right. Basically:

  • Set the tile as checked
  • If the tile is on the board and the neighboring tile matches, increase verticalMatches/horizontalMatches.
  • call method again for next Tile (recursive)

I call these methods inside my checkForMatch method that is called in the game loop:

private void checkIfMatch(int row, int col){ checkIfUpMatch(row, col); checkIfDownMatch(row, col); checkIfLeftMatch(row, col); checkIfRightMatch(row, col); if(verticalMatches >= 3 || horizontalMatches >= 3){ for(int i=0; i<ROWS;i++){ for(int j = 0; j < COLS; j++){ if(array[i][j].isChecked()){ array[i][j].setMatched(true); } } } reFill(); }else{ for(int i=0; i<ROWS;i++){ for(int j = 0; j < COLS; j++){ if(array[i][j].isChecked() && !array[i][j].isMatched()){ array[i][j].setChecked(false); } } } } verticalMatches = 1; horizontalMatches = 1; } 
  • If verticalMatches or horizontalMatches >= 3 we set the checked tiles as matched
  • else we set checked back to false for all the tiles and reset verticalMatches/horizontalMatches

As you can see I call refill after we set all the tiles needed as matched, which looks like this:

private void reFill(){ //refill the board after a match has been made for(int i=0; i<ROWS;i++){ for(int j = 0; j < COLS; j++){ if(array[i][j].isMatched()){ fallDown(i, j); array[i][j].setMatched(false); array[i][j].setChecked(false); } } } } private void fallDown(int row, int col){ //replaces the ID of the removed tile from above Tile removedTile = array[row][col]; if(row+verticalMatches > 7){ //we are at the top so just put in new tiles int random = MathUtils.random(1, TILETYPES); array[row][col].setId(random); return; } Tile changeTile = array[row + verticalMatches][col]; //use vertical matches to set the removed tile to the correct ID removedTile.setId(changeTile.getId()); fallDown(changeTile.getRow(), changeTile.getCol()); return; } 
  • Here we loop through all the matched tiles and call fallDown
  • fallDown replaces the removed tile with the tile above recursively until we are at the top of the board, then we insert new random tiles

That is it, any advice, tips or ideas are welcome, I've spent probably a good 20 hours of coding trying to figure this out. Maybe there is some easier way to do this that I am missing, or maybe I'm just making a few mistakes.

EDIT:

Trying to implement Shiro's solution:

private void checkVertical(int row, int col){ // The current tile we are checking for matches final Tile tile = tiles[row][col]; // The matches of the current tile final List<Tile> matchedTiles = new ArrayList<Tile>(); if(row < 7 && tiles[row + 1][col].getId() == tiles[row][col].getId()){ // 1 up matchedTiles.add(tiles[row + 1][col]); if(row < 6 && tiles[row + 2][col].getId() == tiles[row][col].getId()) // 2 up matchedTiles.add(tiles[row + 2][col]); } if(row > 0 && tiles[row - 1][col].getId() == tiles[row][col].getId()) { // 1 down matchedTiles.add(tiles[row - 1][col]); if(row > 1 && tiles[row - 2][col].getId() == tiles[row][col].getId()) // 2 down matchedTiles.add(tiles[row - 2][col]); } // If we find a match if(matchedTiles.size >= 2) { for(Tile tile : matchedTiles) { final int row = tile.getRow(); final int col = tile.getCol(); tiles[row][col].setId(8); } } } 
Green_qaue
  • 1.9k
  • 4
  • 26
  • 57