我正在写一个俄罗斯方块克隆,我在C#中进行原型设计。最终的代码应该在嵌入式系统上运行(使用8位CPU和非常小的RAM),所以我试图使用天真的算法来清除行。
现在,我的playfield是一个2D数组:
private readonly TetrominoType[][] _playfield;
(其中TetrominoType
是一个枚举,表示无或用于着色块的7种类型之一)
当一行被清除时,我想要就地修改这个数组,这就是我的问题所在。举个例子:
Before After
0 # # # #
1 # # # #
2 # # # #
3 # # # #
4 # # # #
5 #xxxxxx# # #
6 #x xx# # #
7 #xxxxxx# # #
8 #xxxxxx# #x xx#
9 #x xxxx# #x xxxx#
######## ########
我已经确定需要删除第5,7和8行,因此其他行应该会掉落,让我处于右边的状态。
我天真的方式是向后迭代并将线条复制到已清除的线上,基本上是:
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];
}
}
}
这里的问题是上面的行也可能被清除(例如,如果iy == 8
那么我不想复制第7行而是第6行)并且还需要清除复制的行({ {1}}) - 或复制那个反过来需要向上涓流的那条线。
我尝试计算已跳过多少行,但只有在我创建一个新数组然后将它们交换出来时才有效,但是我无法通过就地修改playfield数组来进行数学运算。
这可能很简单,但我只是没有看到算法。有没有人对我如何做到这一点有所了解?
答案 0 :(得分:2)
主要问题是多条清除行,因此我们需要确保当一行中有多条已清除的行时,将所有行都移动到所有行中。由于您有一个列表需要清除哪些行,而不是仅仅复制它上面的行,您可以找到下一个未清除行的距离,并将其上方的所有行移动到多行。例如,您可以这样做:
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];
}
}
}
}
这将计算出一行中有多少条已清除的行,然后将所有行放下那么多行。我希望这有帮助!
答案 1 :(得分:1)
它会起作用吗?
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++;
}