ottijp blog

シェルスクリプトで往年のじゃんけんマシーンを作る

  • 2023-12-05

これは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)"

cf. Bash の構文: 関数から戻り値を返す - まくまくLinux/Shellノート


ottijp
都内でアプリケーションエンジニアをしています
© 2024, ottijp