I'm writing a Tetris-clone and I'm prototyping in C#. The final code is supposed to run on an embedded system (using an 8-Bit CPU and very little RAM), so I'm trying to use a naïve algorithm to do line clear.
Right now, my playfield is a 2D Array:
private readonly TetrominoType[][] _playfield;
(where TetrominoType
is an enum to indicate either None or one of the 7 types, used for coloring blocks)
When a line is cleared, I want to modify this array in-place, which is where my problem is. Take this example:
Before After
0 # # # #
1 # # # #
2 # # # #
3 # # # #
4 # # # #
5 #xxxxxx# # #
6 #x xx# # #
7 #xxxxxx# # #
8 #xxxxxx# #x xx#
9 #x xxxx# #x xxxx#
######## ########
I have already determined that lines 5, 7 and 8 need to be removed and thus other lines should fall down, leaving me with the state on the right.
My naïve way is to iterate backwards and copy the line above a cleared one, basically:
for(int iy = 9; iy >= 0; iy--) {
if(_linesToClear.Contains(iy)) {
for(int ix = 0; ix < 6; ix++) {
_playfield[iy][ix] = _playfield[iy-1][ix];
}
}
}
The problem here is that the line above might also be cleared (e.g, if iy == 8
then I don't want to copy line 7 but line 6) and also that I need to clear the copied line (iy-1
) - or copy the line above that one which in turn need to trickle upward.
I tried counting how many lines I already skipped, but that works only if I create a new array and then swap them out, but I can't get the math work for in-place modification of the playfield array.
It's possibly really simple, but I'm just not seeing the algorithm. Does anyone have some insight how I can do this?
The main problem is multiple cleared lines, so we need to make sure that when you have multiple cleared lines in a row to move everything down through all of them. Since you have a list of which lines need to be cleared, instead of just copying the line above it, you can find how far up the next non-cleared line is, and move everything above it down that many lines. For example, you could do this:
for(int iy = 9; iy >= 0; iy--)
{
if(_linesToClear.Contains(iy))
{
int nextLineIndex = iy-1;
while( _linesToClear.contains(nextLineIndex) && nextLineIndex >= 0 )
{
nextLineIndex--;
}
if ( nextLineIndex >= 0 )
{
int amountToDrop = iy - nextLineIndex
for(int ix = 0; ix < 6; ix++)
{
_playfield[iy][ix] = _playfield[iy-amountToDrop][ix];
}
}
}
}
This would figure out how many cleared lines there are in a row, then drop everything down that many lines. I hope this helps!
Would it work?
int k = 0;
for(int iy = 9; iy >= 0; iy--) {
if(!_linesToClear.Contains(iy)) {
for(int ix = 0; ix < 6; ix++) {
_playfield[iy + k][ix] = _playfield[iy][ix];
}
}
else
k++;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With