在 Linux bash 中,可以使用下面介绍的 shell 脚本来显示各个彩色的俄罗斯方块形状。
硬编码显示彩色的俄罗斯方块
下面的代码使用 ANSI 转义码来设置终端字符的显示颜色,从而显示出彩色的方块内容。
在脚本代码的注释中说明了各个 ANSI 转义码的含义,方便理解。
关于 ANSI 转义码的详细说明,可以参考前面的文章。
假设有一个 colorblocks.sh
脚本,内容如下:
#!/bin/bash
# 显示俄罗斯方块几种基本形状的彩色方块
# 田字形方块
# "\e[43m" 设置字符的背景色为黄色
# "\e[0m" 重置字符属性为默认值,恢复原来的颜色.
echo -e "\e[43m[][]\n[][]\e[0m"
# echo 命令不带参数时,默认输出一个换行符.
echo
# 土字形方块
# "\e46m" 设置字符的背景色为青色
echo -e " \e[46m[]\n[][][]\e[0m"
echo
# Z 字形方块
# "\e[42m" 设置字符的背景色为绿色
echo -e "\e[42m[][]\n\e[0m \e[42m[][]\e[0m"
echo
# L 字形方块
# "\e[44m" 设置字符的背景色为蓝色
echo -e "\e[44m[]\n[][][]\e[0m"
echo
# 一字形方块
# "\e[41m" 设置字符的背景色为红色
echo -e "\e[41m[][][][]\e[0m"
echo
执行 colorblocks.sh
脚本的结果如下:
数字化表示俄罗斯方块的基本形状
上面的 colorblocks.sh
脚本直接硬编码显示俄罗斯方块的几种基本形状,无法指定方块的显示位置。
如果要显示其他形状的方块,也只能硬编码显示,代码无法复用。
实际上,所有横放的俄罗斯方块基本形状都可以由下面的形状缺少部分小方块所得到:
[][][][]
[][][][]
所有竖放的俄罗斯方块基本形状都可以由下面的形状缺少部分小方块所得到:
[][]
[][]
[][]
[][]
即,用 8 个小方块都可以表示所有的俄罗斯方块基本形状。
我们可以用不同的值来表示这 8 个小方块的状态,从而数字化表示对应的基本形状。
例如,用 1 表示要显示某个小方块。用 0 表示不显示某个小方块。
那么,横放的土字形方块可以表示为 0 1 0 0 1 1 1 0。
即,第一行只显示第两个小方块,其他小方块不显示。
第二行显示前面三个小方块,第四个小方块不显示。
其他形状的方块可以类似表示。
由于横放的形状有两行,竖放的形状有四行,还需要另外的状态值来表示换行状态。
可以改成用下面的状态值来进行表示:
- 1:表示显示小方块,且不换行
- 2:表示不显示小方块,且不换行
- 3:表示显示小方块,且换行
- 4 表示不显示小方块,且换行
基于这个定义,把横放的土字形方块表示为 21241112。
把竖放的土字形方块表示为 14131422。
通过控制换行的位置来决定是横放、还是竖放。
使用数字化表示俄罗斯方块的基本形状后,可以把这些形状放到一个数组里面。
通过遍历数组,判断每个小方块的状态值,就可以显示出对应形状的方块。
后续要显示其他形状的方块时,只需要把数字化的形状表示添加到数组即可。
下面的脚本可以基于数字化表示的俄罗斯方块数组来显示对应的方块。
脚本代码的关键点都添加了详细的注释,便于阅读理解。
假设有一个 colorblocks_ext.sh
脚本,内容如下:
#!/bin/bash
# 这个数组用于指定不同方块的背景色
# 1 对应红色. 2 对应绿色. 3 对应黄色
# 4 对应蓝色. 6 对应青色.
COLORS=(1 2 3 4 6)
# 定义下面常量以便说明这些取值的含义
# 显示彩色方块 "[]",且不换行
SQUARE=1
# 显示空白方块 " ",且不换行
EMPTY=2
# 显示彩色方块 "[]",且换行
SQUARE_LF=3
# 显示空白方块 " ",且换行
EMPTY_LF=4
# 横放的俄罗斯方块基本形状有下面几种
# [][] [] [][] [] [][][][]
# [][] [][][] [][] [][][]
# 这些形状都可以由下面形状缺少部分小方块所得到
# [][][][]
# [][][][]
# 在代码中,可以使用不同的值来表示这8个小方块的状态,
# 得到对应的方块形状,方便代码处理.例如,基于上面定义
# 的4个常量值,可以把土字形方块表示为: 21241112. 即,
# 第一行的第一个小方块不显示,显示第二个小方块,第三、
# 第四个小方块不显示.第一行在第四个小方块之后换行.
# 第二行的前三个小方块要显示,第四个小方块不显示.
# 其他形状的方块可以类似表示. 具体如下面的数组所示.
#
# 第一个元素对应横放的田字形方块
# 第二个元素对应横放的土字形方块
# 第三个元素对应横放的 Z 字形方块
# 第四个元素对应横放的 L 字形方块
# 第五个元素对应横放的一字形方块
# 1、2、3、4 的含义如上面注释所示
HORIZONTAL_BLOCKS=(\
"11241122" \
"21241112" \
"11242112" \
"12241112" \
"11132222" \
)
# 竖放的俄罗斯方块基本形状可以由下面形状缺少部分小方块所得到
# [][]
# [][]
# [][]
# [][]
# 不同形状的表示方法可以参考上面横放形状的说明.
#
# 第一个元素对应竖放的田字形方块
# 第二个元素对应竖放的土字形方块
# 第三个元素对应竖放的 Z 字形方块
# 第四个元素对应竖放的 L 字形方块
# 第五个元素对应竖放的一字形方块
VERTICAL_BLOCKS=(\
"11241122" \
"14131422" \
"23131422" \
"13141422" \
"14141414" \
)
function print_block()
{
if [ $# -ne 4 ]; then
echo "Usage: $FUNCNAME line column bg_color square_list"
return 1
fi
# 第一个参数指定显示方块的起始行
local base_line="$1"
# 第二个参数指定显示方块的起始列
local base_column="$2"
# 第三个参数指定显示方块的背景色
local bg_color="$3"
# 第四个参数指定显示方块的形状
local square_list="$4"
local square i
# 使用 "\e[line;columnH" 转义码把光标移动到指定起始位置
# 后续会从这个起始位置开始输出字符,指定方块的显示位置.
printf "\e[${base_line};${base_column}H"
# 每个方块最多有 8 个小方块组成,遍历显示每一个小方块
for ((i = 0; i < 8; ++i)); do
# 从方块形状列表中获取每一个小方块的形状.
# 具体形状的取值含义如上面注释所示.
square=${square_list:i:1}
if [ $((square % 2)) -ne 0 ]; then
# 如果小方块的值是奇数,表示要显示彩色小方块
printf "\e[4${bg_color}m[]\e[0m"
else
# 如果小方块的值是偶数,表示要显示空白小方块
printf " "
fi
# 如果小方块的值大于 2,表示要换行.
# 下面把光标移动到下一行.列数保持起始列数不变.
if [ $square -gt 2 ]; then
printf "\e[$((++base_line));${base_column}H"
fi
done
}
# 由于后面指定从第三行开始显示彩色方块,
# 为了避免已有内容干扰显示,先清屏.
clear
echo "Display color blocks."
for ((index = 0; index < 5; ++index)); do
# 从第三行开始显示横放的所有方块.每个方块最多占据 8 个字符.
# 指定的列数为 10 的倍数,不同方块之间空两行
print_block 3 $((index*10)) ${COLORS[index]} ${HORIZONTAL_BLOCKS[index]}
# 从第六行开始显示竖放的所有方块.
print_block 6 $((index*10)) ${COLORS[index]} ${VERTICAL_BLOCKS[index]}
done
echo
执行 colorblocks_ext.sh
脚本的结果如下:
这里只列举了几种基本形状。
如果要显示其他形状,可以把具体的数字化表示值添加到对应的数组里面,就能显示出来。