我想了解this实施俄罗斯方块。
我有几个问题。
在update_score函数中,
if (( score > LEVEL_UP * level)) ; then # if level should be increased
((level++)) # increment level
pkill -SIGUSR1 -f "/bin/bash $0"
根据一个单独的流程调整延迟有什么用?为什么要使用SIGUSR1
和SIGUSR2
?
在draw_piece函数中,为什么乘以8?我不明白转换是如何发生的,或者#"旋转"在这里实施。
for ((i = 0; i < 8; i += 2)) {
# relative coordinates are retrieved based on orientation and added to absolute coordinates
((x = $1 + ${piece[$3]:$((i + $4 * 8 + 1)):1} * 2))
((y = $2 + ${piece[$3]:$((i + $4 * 8)):1}))
xyprint $x $y "$5"
...
}
我也不理解涉及的语法:这里。
在clear_next中,为什么需要draw_next ${filled_cell//?/ }
而不仅仅是${filled_cell}
? //
表示什么?
答案 0 :(得分:3)
我是初学者,通常会编写脚本编程和编程,我一直在尝试理解俄罗斯方块的这种实现 [在shell中]
不知何故,我怀疑你可以找到更简单的程序开始。
根据一个单独的流程调整延迟有什么用?为什么要使用[SIGUSR1]和[SIGUSR2]?
我不认为调整延迟的单独过程,但实施计时器。即使程序正在等待播放器提供输入,计时器也必须运行,如果shell函数没有在read
上提供任何超时,则必须将其导出到另一个进程。那么你得到脚本末尾的内容,分为计时器,用户输入处理程序和实际游戏逻辑,前两个输出到最后一个:
(ticker & reader) | (controller)
Bash的read
确实有-t
标志用于超时,因此如果它在Bash中实现,则可能不需要额外的计时器进程。但是,将计时器放在外部进程中也会使其独立于用户输入,每次用户点击按钮时,read
超时都会重置。解决这个问题需要某种方法来准确地确定经过的时间(或者在read
上使用非常短的超时并计算滴答声。)
SIGUSR1
和SIGUSR2
只是&#34;无辜&#34;对整个系统没有意义的信号,因此可以在这里使用。当然你可以使用其他人,但如果他们想要停止游戏,那么抓住SIGINT
或SIGHUP
会让用户烦恼。
在draw_piece函数中,为什么乘以8?
((x = $1 + ${piece[$3]:$((i + $4 * 8 + 1)):1} * 2))
piece
数组包含各个部分的不同形状和方向。一块是4个方块大,每个方块需要两个坐标,所以我们每件/方向得到8个数字。例如,S片段的字符串为0001111201101120
,因此它有两个方向:
yx yx yx yx yx yx yx yx
00 01 11 12 01 10 11 20
这件作品看起来像这样:
012 012
0 xx. 0 .x.
1 .xx 1 xx.
2 ... 2 x..
${variable:position:length}
表示法从给定变量中选择一个子字符串,因此程序从较大的字符串中获取所需的单个数字。这是一种实现阵列的奇怪方式。
在clear_next中,为什么需要draw_next
${filled_cell//?/ }
......?//
表示什么?
${parameter/foo/bar}
构造是模式替换(参见例如Bash's manual on parameter expansion,查找&#34;替换&#34;)。无论foo
的值parameter
匹配,都会被bar
替换,结果会被展开。使用双斜杠,所有匹配都被替换,只有一个斜杠,只有第一个。问号与filename globs匹配任何字符,因此有效地生成一串空格,与原始字符串一样长。
例如:
$ str="hallo hallo"
$ echo "${str/a/e}"
hello hallo
$ echo "${str//a/e}"
hello hello
$ str="abc"
$ echo "x${str//?/ }x"
x x