我正在尝试按以下形式画一棵树
*
***
*****
*******
*********
如你所见,我每行都需要空格和“*”星号,但我无法按照我想要的方式得到它
#!/bin/bash
display_tree() {
local rows=$1
local columns=$2
for ((i=0; i<$rows; i++))
do
#spaces loop
for ((j=0; j<$columns; j++))
do
echo -n " "
#drawing tree loop
for ((a=0; a<$(($i + 1)); a++))
do
echo -n "*"
done
done
echo
done
}
if [ $# -eq 2 ]; then
display_tree $1 $2
else
echo "Usage: $0 rows columns"
fi
这似乎对我有用。建议为“列”参数使用奇数。 当列 = 2*行 - 1 时看起来最漂亮。代码中最长的行执行一些基本代数运算,特别是线性插值,用于计算给定行中要显示的星星数量。
#!/bin/bash
# Christmas tree ASCII drawer
# works nicest for odd integers
spaces() {
for ((i=0; i<$1; i++)) ; do
echo -n " "
done
}
stars() {
for ((i=0; i<$1; i++)) ; do
echo -n "*"
done
echo ""
}
display_tree() {
local rows=$1
local columns=$2
# render
for (( r=1; r <= $rows; r++ )); do
s=$(( (((columns-1) * (r-1)/(rows-1) + 1)/2)*2 +1 ))
spaces $(((columns-s)/2))
stars $s
done
}
if [ $# -eq 2 ]; then
display_tree $1 $2
else
echo "Usage: $0 rows columns"
fi
输出示例:
./display_tree.sh 5 21
*
*******
***********
*****************
*********************
./display_tree.sh 30 59
*
***
*****
*******
*********
***********
*************
***************
*****************
*******************
*********************
***********************
*************************
***************************
*****************************
*******************************
*********************************
***********************************
*************************************
***************************************
*****************************************
*******************************************
*********************************************
***********************************************
*************************************************
***************************************************
*****************************************************
*******************************************************
*********************************************************
***********************************************************
这个解决方案的逻辑非常简单,可能最好的解释方法是在文本编辑器中绘制树的几个级别,并计算每次迭代的星星和空格的数量。您很快意识到它涉及生成一组数字。例如:
3 1
2 3
1 5
0 7
您现在要做的就是设置一个起点($COLUMNS/2)。 $(eval ...) 部分只是打印空格和星号而不使用的技巧 一个循环。需要 Eval,因为大括号 shell 扩展 {1..$var} 没有它就无法工作。
spaces=$(($COLUMNS/2));
for ((i=1; i < $LINES; i+=2));
do echo "$(eval printf '\ %.0s' {1..$spaces}) $(eval printf '*%.0s' {1..$i})";
((spaces--));
done;
出于某种原因,六年后,我想起了这件事。代码还可以进一步简化:
s=$(($COLUMNS/2));
for ((i=1; i<$LINES; i+=2)); do
printf "%${s}s";
printf "%${i}s\n" | tr " " "*";
((s--));
done
letters=( \" \');while true;do clear; letter=${letters[$[RANDOM%${#letters[@]}]]}; [[ $letter == \" ]] && color=35 || color=32;m=2;i=77;p=$(($i/2-1)); while [[ $m -le $i ]];do printf "%${p}s" ;printf "\e[4;${color}m${letter}%.0s\e[m" $(seq $m);echo;m=$[m+2];((p--));done;sleep 1;done