When you drop a piece, you check for overlapping empty sprites. Since those have a collision size of 10 x 10 boxes and your game piece a collision box for 42 x 42 pixels, there are places, where your gamepiece overlaps multiple empty sprites. In that case, two or even three of the empty sprites are destroyed and only one is created -> you end up with empty spaces in your grid.
After your overlapping condition, you could add "pick nearest empty" or (even better) compare two values: distance(gamepiece.x, gamepiece.y, empty.x, empty.y) < gamepiece.width - empty.width * 2
This way you will end up with only one empty picked, and in the case of the distance expression, you also get some snapping back, when the game piece is in the middle of two empty pieces and when it is not sure if the user wanted the piece to drop on empty 1 or empty 2.
And here the checking function I would have done (although I would probably input the piece information into an array and iterate over that):
It's a bit simpler imo, you have a queue of pieces to check (starting with the exchanged piece), this looks at the pieces around it and finds pieces that have not been looked at (queued) before (status = 0); those pieces are added to the queue. When the queue is empty, you've found all adjacent pieces of the same color.
Of course you can pack these 4 events of looking around into each direction into a for loop, but while it saves space in the event sheet, I don't think it will be faster at execution, since calculations won't get less.