Bash だけで*1動きのあるスクリプト*2を作成します。
一種のゲームのような動作をしますが、勝ち負けは気にしません。
競走馬「@」を用意し、直線の走路を走らせます。
いずれかが一着でゴールしたら終了です*3。
一着にならなかった馬は、ゴール通過のチャンスがありません。
なので、一般的な競馬とはかなり異なります。
*1外部呼び出しの seq コマンドを使っているので、正確には「だけ」になっていません。
インデックス処理なので本当は for((…)) を使うべきだけど、シェルらしさを優先させました。
*2Bash の場合はプログラミングが可能なので「スクリプト」=「プログラム」です。
JCL や SQL のようにプログラミングをしない「スクリプト言語」も存在します。
*3処理は同着を許容しているので、複数の一着がありえます。
1. スクリプトファイルの作成
derby.sh2. 実行
*4「エスケープシーケンス」という特殊文字列を定義しています。
#!/usr/bin/bash # derby.sh # Usage: # bash ./derby.sh # 競走馬の名前を定義する (表示用) # ' ' は全角の空白文字。表示をそろえるために必要 Horses=( 'ディープインパクト' 'オルフェーヴル ' 'オグリキャップ ' 'ウオッカ ' 'サイレンススズカ ' ) # 競走馬それぞれの歩数を用意する GallopSteps=(0 0 0 0 0) # 競走馬の頭数を数える。覚えにくいが Bash ではこう記述する HorseCnt=${#Horses[@]} # コースの長さを定義する CourseLength=40 # 画面クリアの機能を定義する*4 CLEAR="echo -n -e \e[2J\e[1;1H" # どれか 1 頭でもゴールするまで繰り返す finish=false while [ $finish == false ] do # つまづく馬を一頭だけ適当に決める*5 stumble=$(($RANDOM % $HorseCnt)) # 全競走馬の歩数を一歩進める for i in `seq 0 $(($HorseCnt - 1))` do if [ $i == $stumble ]; then # つまづく馬は進ませない : # Bash は if ブロック内に命令がないとエラーになるので : を置く else # 馬を一歩進ませる GallopSteps[$i]=$((${GallopSteps[$i]} + 1)) fi # コースの最後に到達した馬がいたら終了フラグを立てる if [ ${GallopSteps[$i]} -ge $CourseLength ]; then finish=true fi done # 画面をクリア (初期化) する $CLEAR # 全競走馬と歩数を表示する for i in `seq 0 $(($HorseCnt - 1))` do # 馬の名前を表示する echo -n ${Horses[$i]} # 歩数とスタートラインを表示する dist=${GallopSteps[$i]} printf '%2d!' $dist # スタートラインから現在位置まで空白文字を表示する for j in `seq 0 $(($dist - 1))` ; do echo -n ' ' done # 馬の現在位置にマークを表示する echo -n '@' # 現在位置からゴールラインまで空白文字を表示する for j in `seq $dist $(($CourseLength - 1))` ; do echo -n ' ' done # ゴールラインを表示する echo '|' done # 実行を少し休む sleep 0.5 done
様々な種類があり、ここでは画面をクリアする指示を定義しています。
*5 $RANDOM は Bash に用意されている特殊な変数で、読み込むたびに異なる数値を返します。(0~32767)
ここでは、競走馬の数 (= 5) で割ったあまりを求めることにより、0~4 のどれかを得ています。
ファイルに保存してから実行していますが、上記スクリプトを直接タイプしても実行可能です。
$ bash ./derby.sh
(デモなので繰り返し表示しています。実際は 1 回で終了します)