シェルスクリプトで往年のじゃんけんマシーンを作る
これはInfocom Advent Calendar 2023 5日目の記事です.
シェルスクリプトの練習として,往年のじゃんけんマシーンを作ってみました.
環境
- macOS: 13.5 (Ventura)
- zsh: 5.9
コード
rps.sh
#!/bin/zsh
signs=(✊ ✋ ✌)
# generage cpu sign
# 1: rock✊
# 2: paper✋
# 3: scissors✌
generate_cpu_sign() {
cpu=$((RANDOM % 3 + 1))
}
# read player sign
read_player_sign() {
while true; do
echo -n "r(ock)/p(aper)/s(cissors): "
read -k 1 you
echo
case $you in
"r") you=1; break;;
"p") you=2; break;;
"s") you=3; break;;
esac
done
}
# judge win/lose/draw
judge() {
case "$(($you - $cpu))" in
"0") echo "draw";;
"1" | "-2") echo "win";;
*) echo "lose";;
esac
}
# print both signs
print_both_signs() {
if [ $aiko -eq 0 ]; then
echo "しょ!👱${signs[$you]} ${signs[$cpu]}🤖"
else
echo "ぽん!👱${signs[$you]} ${signs[$cpu]}🤖"
fi
}
while true; do
# start session
aiko=1
generate_cpu_sign
echo "じゃ〜んけ〜ん・・・"
while true; do
read_player_sign
print_both_signs
case $(judge) in
"draw")
sleep 1
aiko=0
generate_cpu_sign
echo "あ〜いこ〜で・・・"
;;
"win")
sleep 1
echo "フィーバー!🎉"
break
;;
"lose")
sleep 0.25
echo "ズコー"
break
;;
esac
done
echo
sleep 1
done
実行例
どうでしょう.あのじゃんけんマシンのBGMが脳内再生されませんか. 負けた時の「ズコー」だけ表示が早いのがミソです.
練習を通して学んだこと
readの-kオプション
プレイヤによる入力は改行を不要とし,r/p/sのキーを押すだけで確定させたかったので,調べたところread
ビルドイン関数に-k
オプションというのがありまして,それを使うことで実現できました.
bashは非対応のようです(macに入っている3.2.57で確認).
以下はman zshbuiltins
からの抜粋です.
-k [ num ]
Read only one (or num) characters. All are assigned to the first name, without word splitting. This flag is ignored when -q is
present. Input is read from the terminal unless one of -u or -p is present. This option may also be used within zle widgets.
Note that despite the mnemonic `key' this option does read full characters, which may consist of multiple bytes if the option MULTIBYTE
is set.
cf. シェルスクリプトで1文字だけ入力させる方法 - vorfee’s Tech Blog
関数の戻り値として文字列を返す
関数のreturn
は0-255しか返せないので,文字列を戻り値のように返したい場合は標準出力に出してコマンド置換してその値を取ることで実現できました.
hoge() {
echo hoge
}
echo "hoge ret: $(hoge)"