【发布时间】:2014-02-04 02:54:32
【问题描述】:
我正在编写俄罗斯方块克隆,并且正在使用 C# 进行原型设计。最终的代码应该在嵌入式系统上运行(使用 8 位 CPU 和非常少的 RAM),所以我尝试使用一种简单的算法来清除行。
现在,我的运动场是一个 2D 数组:
private readonly TetrominoType[][] _playfield;
(其中TetrominoType 是一个枚举,表示 None 或 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 行)并且我需要清除复制的行(iy-1 ) - 或复制该行上方的行,而该行又需要向上滴流。
我尝试计算我已经跳过了多少行,但这只有在我创建一个新数组然后将它们换出时才有效,但我无法获得就地修改运动场数组的数学工作。
这可能真的很简单,但我只是没有看到算法。有没有人知道我该怎么做?
【问题讨论】:
-
它的性能不会那么好,但是您是否考虑过扫描您的比赛场地以查找 single 已删除的线,将其删除,并相应地调整其余部分,然后重复此算法直到没有删除线?这种“扫描”算法通常用于解构依赖图——虽然效率低下,但它们确实很容易推理并且可能适合这里的账单。另一方面,它们可能效率不高。
-
@KirkWoll 我想了想,虽然没有测试它似乎效率低下,所以我可能会再试一次。即使在 1 MHz 6502 处理器(目标)上,也应该相当快。虽然感觉有点太蛮力了,但话又说回来,有时蛮力正是需要的。
-
我认为通常的代码是“从下到上,复制所有应该保留的行,用空行填充其余行” - 只需记住 2 个索引 - 要写入的当前行和当前行读取(读取> =写入)...此外,您可能需要删除一行/重绘,具体取决于您要显示的内容。
-
@MichaelStum 我建议使用
List<TetrominoType[]>,这样当您删除一行时,您只需执行List.Remove(); -
@MatthewPigram 事实上,如果 C# 是最终的语言,我会使用它。我用它作为原型/概念证明来理解算法,最终程序将在 4k RAM 系统上用 6502 汇编编写,因此我尽可能保持简单:)
标签: c# .net arrays algorithm tetris