如何在 Bash 中绘制 Hangman 而无需为每个案例嵌入 echo 语句?

How can I draw Hangman in Bash without embedding echo statements for each case?

我正在 Bash 做一个刽子手的任务。它完全可以工作,但是它的一部分编码非常糟糕,以至于会引起一种瘙痒。我说的是打印 "hanging the man"

的进度
print_hangman(){

if [[ $attempts = 0 ]]
then
    echo ""
    echo ""
    echo ""
    echo ""
    echo ""
    echo ""
    echo ""
    echo ""
    echo ""
    echo ""
    echo ""
    echo ""
    echo ""

elif [[ $attempts = 1 ]]
then
    echo "      "
    echo "               "
    echo "               "
    echo "               "
    echo "               "
    echo "               "
    echo "               "
    echo "               "
    echo "               "
    echo "               "
    echo "               "
    echo "               "
    echo "_______________"

elif [[ $attempts = 2 ]]
then
    echo "      "
    echo "               "
    echo "               "
    echo "               "
    echo "               "
    echo "               "
    echo "               "
    echo "               |"
    echo "               |"
    echo "               |"
    echo "               |"
    echo "               |"
    echo "_______________|"

elif [[ $attempts = 3 ]]
then
    echo "         "
    echo "               |"
    echo "               |"
    echo "               |"
    echo "               |"
    echo "               |"
    echo "               |"
    echo "               |"
    echo "               |"
    echo "               |"
    echo "               |"
    echo "               |"
    echo "_______________|"

elif [[ $attempts = 4 ]]
then
    echo "      __________"
    echo "               |"
    echo "               |"
    echo "               |"
    echo "               |"
    echo "               |"
    echo "               |"
    echo "               |"
    echo "               |"
    echo "               |"
    echo "               |"
    echo "               |"
    echo "_______________|"

elif [[ $attempts = 5 ]]
then
    echo "      __________"
    echo "     |         |"
    echo "     |         |"
    echo "   _/_\_       |"
    echo "    |_|        |"
    echo "               |"
    echo "               |"
    echo "               |"
    echo "               |"
    echo "               |"
    echo "               |"
    echo "               |"
    echo "_______________|"

elif [[ $attempts = 6 ]]
then
    echo "      __________"
    echo "     |         |"
    echo "     |         |"
    echo "   _/_\_       |"
    echo "    |_|        |"
    echo "     |         |"
    echo "     |         |"
    echo "     |         |"
    echo "     |         |"
    echo "               |"
    echo "               |"
    echo "               |"
    echo "_______________|"

elif [[ $attempts = 7 ]]
then
    echo "      __________"
    echo "     |         |"
    echo "     |         |"
    echo "   _/_\_       |"
    echo "    |_|        |"
    echo "     |         |"
    echo "     |         |"
    echo "     |         |"
    echo "     |         |"
    echo "    /          |"
    echo "   /           |"
    echo "               |"
    echo "_______________|"

elif [[ $attempts = 8 ]]
then
    echo "      __________"
    echo "     |         |"
    echo "     |         |"
    echo "   _/_\_       |"
    echo "    |_|        |"
    echo "     |         |"
    echo "     |         |"
    echo "     |         |"
    echo "     |         |"
    echo "    / \        |"
    echo "   /   \       |"
    echo "               |"
    echo "_______________|"

elif [[ $attempts = 9 ]]
then
    echo "      __________"
    echo "     |         |"
    echo "     |         |"
    echo "   _/_\_       |"
    echo "    |_|        |"
    echo "     |         |"
    echo " ----|         |"
    echo "     |         |"
    echo "     |         |"
    echo "    / \        |"
    echo "   /   \       |"
    echo "               |"
    echo "_______________|"

elif [[ $attempts = 10 ]]
then
    echo "      __________"
    echo "     |         |"
    echo "     |         |"
    echo "   _/_\_       |"
    echo "    |_|        |"
    echo "     |         |"
    echo " ----|----     |"
    echo "     |         |"
    echo "     |         |"
    echo "    / \        |"
    echo "   /   \       |"
    echo "               |"
    echo "_______________|"
fi

}

Bash 中有没有办法让这段代码占用更少的行数?我在想,也许你可以采用标准,然后只为正在更改的行编写行。例如,在 attempt = 1 时,您只需更改 13 行中的一行。

也许吧?

#!/bin/bash

read -r -d '' hex <<'EOF'
1f8b080025bbce580003535040055c0ac3488067b038841a02f16860b0f8
ae862a02689eab21ec3bead84b1f015cbe438acdc1e254320488f55d0dba
216802f1faf131f1282a6ae26bd0b4d0dc331802f4f41d2133881118d6be
d347f30c127f58f82e06c37731a85a0685ef74816098fb0e44d0d777004c
bdfc0d8a090000
EOF
mapfile -d$'4' frames < <(printf "%b" $(sed 's/../\x& /g' <<<"$hex") |gzip -d)
#here you have the array "frames[@]" - with the pictures

for frame in "${frames[@]}"
do
    clear
    printf "%s\n" "$frame"
    sleep 0.3
done

你的 bash 不支持 mapfile -d,你可以使用 mapfile -d .... 代替 mapfile -d .... 行:

n=0
while IFS=$'4' read -r -d $'4' f
do
        frames[$n]="$f"
        let n++
done < <(printf "%b" $(sed 's/../\x& /g' <<<"$hex") |gzip -d)

工作原理:

  • 图片存储为 gzip 十六进制编码字符串。
  • sed 's/../\x& /g' 将字符串转换为 \x1f \x8b
  • 的列表
  • printf "%b" 打印字符
  • 最后 gzip -d 解码整个流
  • "stream" 是一系列帧,每个帧除以 ^L (CTRL-L) 字符
  • mapfile 使用分隔符 ^L
  • 将流读入数组 frame
  • 完成:)

输出 - 每帧如下所示

________________







               |
               |
               |
               |
               |
_______________|

               |
               |
               |
               |
               |
               |
               |
               |
               |
               |
               |
_______________|
      __________
               |
               |
               |
               |
               |
               |
               |
               |
               |
               |
               |
_______________|
      __________
     |         |
     |         |
   _/_\_       |
    |_|        |
               |
               |
               |
               |
               |
               |
               |
_______________|
      __________
     |         |
     |         |
   _/_\_       |
    |_|        |
     |         |
     |         |
     |         |
     |         |
               |
               |
               |
_______________|
      __________
     |         |
     |         |
   _/_\_       |
    |_|        |
     |         |
     |         |
     |         |
     |         |
    /          |
   /           |
               |
_______________|
      __________
     |         |
     |         |
   _/_\_       |
    |_|        |
     |         |
     |         |
     |         |
     |         |
    / \        |
   /   \       |
               |
_______________|
      __________
     |         |
     |         |
   _/_\_       |
    |_|        |
     |         |
 ----|         |
     |         |
     |         |
    / \        |
   /   \       |
               |
_______________|
      __________
     |         |
     |         |
   _/_\_       |
    |_|        |
     |         |
 ----|----     |
     |         |
     |         |
    / \        |
   /   \       |
               |
_______________|

如何创建十六进制字符串

  • 每帧创建一个文件,例如 xx00xx01、...
  • 使用下面的make_hex.sh作为bash make_hex.sh xx*
mk_stream() {
    for file in "$@"
    do
        cat "$file"
        printf "%c" $'4'
    done
}
mk_stream "$@" | gzip | xxd -ps