博客首页 注册 建议与交流 排行榜 加入友情链接
推荐 投诉 搜索: 帮助

剑心通明的资料库

文章均为转载,本人不负因参考它所导致的一切后果,请谨慎参考!如您的文章不愿被转载,请点击此处联系本人!
  jxtm.cublog.cn

关于作者
姓名:剑心通明
职业:高级工程师(专修灵魂^_^)
年龄:20出头30不到
位置:网络上一节点
个性介绍:努力学习每一天!
倾心打造:http://www.bsdlover.cn
http://bbs.bsdlover.cn
BSD爱好者的乐园!
|| << >> ||
我的分类


一个演示汉诺塔的脚本
主要是练习用tput来设置终端的前景,背景色,以及定位光标
水平菜,代码很长,让各位见笑了

代码:
#!/bin/bash

##usage: sh $0 n
##
## ------------------->X
## |
## |
## |
## |   disk 1 -------->     ()
## |   disk 2 -------->    (())
## |   disk 3 -------->   ((()))
## |   disk 4 -------->  (((())))   
## |   ............     ..........
## V   disk n-1 -->   ((((((()))))))
## Y   disk n --> ___(((((((())))))))______   _________________________   ________________________
##     ground -->|_________________________| |_________________________| |________________________|
##                         A                             A                            A
##                         |                             |                            |
##                         |                             |                            |
##                     source,1                        aid,2                  destination,3

usage="sh $0 non-negative number"
disks=$1
colums=$((($(tput cols)-4)/3))

## 底座的 Y 坐标
groundat=$(($(tput lines)-2))

## 底座source(或1)处,最顶层盘的中心坐标
sourcex=$(($colums/2))
sourcey=$(($groundat-$disks))

## 底座aid(或2)处,最顶层盘的中心坐标
aidx=$(($colums+2+$sourcex))
aidy=$(($groundat-1))
aidfirst=0

## 底座destination(或3)处,最顶层盘的中心坐标
destinationx=$(($colums*2+4+$sourcex))
destinationy=$(($groundat-1))
destinationfirst=0

coordinate=''


initdraw()
{
    init_drawdisks
    init_drawground
}

init_drawground()
{
    index=1
    tput cup $groundat 0
   
    for i in 1 2 3
    do
tput setab $((1+$i))
while(($index<=$i*$colums+($i-1)*2))
do
     echo -ne ' '
     index=$(($index+1))
done
tput sgr0
echo -n '  '
index=$(($index+2))
    done

    tput cup $(tput lines) 0
}

init_drawdisks()
{
    for((offset=0,n=$disks;n>0;n--,offset++))
    do
drawdisk $(($colums/2)) $(($groundat-1-$offset)) $((2+($n-1)*2)) $n
    done
}

drawdisk()
## 画一个中心在 ($1,$2),长度为 $3 的盘子
## 盘子的序号 $4 决定盘子的颜色
{
    disk=''
    for((tmp=$3/2;tmp>0;tmp--)); do disk=${disk}')'; done
    for((tmp=$3/2;tmp>0;tmp--)); do disk='('${disk}; done
    tput setab $(($4%8+1))
    tput cup $2 $(($1-$3/2))
    echo -n "$disk"
    tput sgr0
}

destroydisk()
## 将中心位置为 ($1,$2),长度为 $3 的盘子销毁
{
    tput cup $2 $(($1-$3/2))
    empty=''
    for((tmp=$3;tmp>0;tmp--)); do empty=' '$empty; done
    echo -n "$empty"
    tput cup 0 0
}

moving()
## 将第 $5 个盘子从 ($1,$2) 移动到 ($3,$4)
{
    verticaltop=$(($groundat-1-$disks))
    horizspace=$(($3-$1))
    x=$1
    y=$2
    length=$((2+($5-1)*2))

    while(($y>=$verticaltop))
    do
destroydisk $x $y $length
y=$(($y-1))
drawdisk $x $y $length $5
# sleep 0.5
    done

    sign=$(($horizspace<0?-1:1))
    while(($3-$x!=0))
    do
destroydisk $x $y $length
x=$(($x+1*$sign))
drawdisk $x $y $length $5
# sleep 0.5
    done

    while(($y<$4))
    do
destroydisk $x $y $length
y=$(($y+1))
drawdisk $x $y $length $5
# sleep 0.5
    done
}

hanoi()
{
    bool1=$(($disks%2))
   
    for((s=1;s<2**$disks;s++))
    {
index=$(factor $s | sed 's/.*: //;s/2 /2\n/g' | grep '^2$' -c)
step=$(((s/(2**$index)+1)/2))
index=$(($index+1))
bool2=$(($index%2))
fromtonum=''

        ## 求出第 s 步时,应将第 $index 个盘子从底座(1或2或3)移动到底座(1或2或3)
if(($bool1==$bool2))
then
     case $(($step%3)) in
  1)
      fromtonum='1 3';;
  2)
      fromtonum='3 2';;
  0)
      fromtonum='2 1';;
     esac
else
     case $(($step%3)) in
  1)
      fromtonum='1 2';;
  2)
      fromtonum='2 3';;
  0)
      fromtonum='3 1';;
     esac
fi
fromtonum=${fromtonum}" $index"

## 按照盘子序号和底座序号计算出移动的源及目的的坐标 coordinate
_getcoordinat $fromtonum

tput cup $groundat $(($colums+1+$colums/2))
tput setab 3
tput setaf 0
echo $s
tput sgr0

## 移动盘子
moving $coordinate

    }

}

_getcoordinat()
## 第 $3 个盘子要从底座 $1 移动到底座 $2,据此计算出移动的源坐标和目的坐标
{
    case "$1" in
1)
     coordinate="$sourcex $sourcey "
     sourcey=$(($sourcey+1));;
2)
     coordinate="$aidx $aidy "
     aidy=$(($aidy+1));;

3)
     coordinate="$destinationx $destinationy "
     destinationy=$(($destinationy+1));;
    esac

    case "$2" in
1)
     sourcey=$(($sourcey-1))
     coordinate=${coordinate}"$sourcex $sourcey";;
2)
     aidy=$(($aidy-1*$aidfirst))
     coordinate=${coordinate}"$aidx $aidy"
     aidfirst=1;;
3)
     destinationy=$(($destinationy-1*$destinationfirst))
     coordinate=${coordinate}"$destinationx $destinationy"
     destinationfirst=1;;
    esac

    coordinate=${coordinate}" $3"
}

################ 开始 #####################
[[ -z "$disks" || "$disks" =~ [^[:digit:]] ]] && echo "usage: ""$usage" && exit
(( $disks+2>$groundat || (2+($disks-1)*2)*3+4>$(tput cols))) && echo "screen is too small, reseize it" && exit
tput clear
tput civis
initdraw
stty -echo

sleep 0.5
for((i=5;i>=0;i--))
do
    tput cup $(($(tput lines)/2)) $(($(tput cols)/2-2))
    tput setab $i
    echo ' '$i' '
    sleep 0.6
    tput sgr0
    tput cup $(($(tput lines)/2)) $(($(tput cols)/2-2))
    echo '   '
    sleep 0.4
done
tput sgr0
tput cup $(($(tput lines)/2)) $(($(tput cols)/2))
echo " "
hanoi

stty echo
tput reset
tput sgr0
tput cup $(tput lines) 0
tput cnorm

 原文地址 http://www.bsdlover.cn/html/41/n-841.html
发表于: 2008-05-03,修改于: 2008-05-03 11:05,已浏览438次,有评论0条 推荐 投诉


网友评论
 发表评论