【Mac】Apple Scriptのdisplay dialogの練習がてらじゃんけんアプリを作ってみる

# はじめに
先日、
[【Mac】シェルスクリプトをmacOS App化してみる](https://qiita.com/soh19/items/7b3393266ec74378b58a)
という記事を書かせていただきましたが、本当はこっちがやりたかったんです。
App化するところは↑の記事を参考にしてください。

Apple Scriptを使うとユーザーに選択画面を表示したり、テキスト入力画面を表示させることが簡単にできます。
シェルから呼び出せるので結構気軽に使えます。
いろいろなスクリプトで使っているのですが、ごちゃごちゃしてきたのでじゃんけんアプリという形でまとめてみようと思います。

# 使用環境
macOS 10.13.6
特に関係ないと思います。(なんとなくアップグレードしてない・・・)

# ざっくり設計
- じゃんけんしますか？(YES or NO分岐)
- あなたのお名前は？(テキストボックス入力)
- 名前の確認(入力された変数の代入)
- 出す手の選択(ボタン3つのパターン)
- 結果表示(変数の代入と繰り返し)

# じゃんじゃん内容
スクリプトにする用と、ターミナルで表示を試す用の二つ記載します。
ターミナルで試す用は(試)とつけます。
スクリプトにする用をコピペした後に関数名を実行でもOKです。
最終的にはスクリプトにする用のみマージします。

## じゃんけん、やるかやらないか
後々、繰り返し使っているので`doOrNotCheck`という名前の関数として括っています。
doOrNot=$( ~ )という部分で`doOrNot`という変数にじゃんけんをやるかやらないかの回答("はい" or "いいえ")を返しています。
Apple Scriptを呼び出す場合は、`osascript`を利用します。
`EOF`と`EOF`の間に記述されているのがApple Script部分となります。

```shell:やるかやらないか.sh
doOrNotCheck () {
doOrNot=$(osascript << EOF
display dialog "私とじゃんけんしますか？" with title "じゃんけんゲーム" with text buttons {"いいえ","はい"} default button 2
button returned of result
EOF)
}
```

```shell:(試)やるかやらないか.sh
osascript -e 'display dialog "私とじゃんけんしますか？" with title "じゃんけんゲーム" with text buttons {"いいえ","はい"} default button 2'
```

**display dialog**：表示するメッセージ
**with title**：タイトル部分に表示するメッセージ
**with text buttons**：表示するボタン
**default button 2**：2番目のボタンをデフォルトにする
**button returns of result**：押されたボタンの値を返す

そう、普通に英語っぽいんですよね。Apple Script。
実行するとこんな感じになります。
<img width="532" alt="スクリーンショット 2019-12-03 11.54.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268331/56d4592b-08a7-223e-9a32-18a8fd3249d5.png">

## (分岐)じゃんけんをやらないを選択した場合
こちらは関数化せずに1行で書いてます。
1行で呼び出す場合は`osascript -e`で呼び出してApple Scriptを記述していきます。

```shell:やらないの・・・.sh
osascript -e 'display dialog "ケチ！" buttons {"(´･ω･`)"} with icon 2 with title "じゃんけんゲーム" '
```
**display dialog**：表示するメッセージ
**buttons**：ボタンに表示するメッセージ
**with icon 2**：左側に表示するアイコンを指定します
**with title**：タイトル部分に表示するメッセージ

こんな感じになります。
<img width="532" alt="スクリーンショット 2019-12-03 11.57.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268331/1945c76a-9107-9f50-f3f7-d3b255ce45cc.png">

## (はいを選択した場合)あなたはだあれ？
`nameInput`という名前の関数として括っています。
name=$( ~ )という部分で`name`という変数にユーザーが入力したテキストを返しています。
`EOF`と`EOF`の間に記述されているのがApple Script部分となります。

```shell:あなたはだあれ？.sh
nameInput () {
name=$(osascript << EOF
display dialog "あなたのお名前は？" with title "じゃんけんゲーム" default answer "ここに名前を入力してください" buttons {"OK"} default button 1
text returned of result
EOF)
}
```

```shell:(試)あなたはだあれ？.sh
osascript -e 'display dialog "あなたのお名前は？" with title "じゃんけんゲーム" default answer "ここに名前を入力してください" buttons {"OK"} default button 1'
```

**display dialog**：表示するメッセージ
**with title**：タイトル部分に表示するメッセージ
**default answer**：：テキストボックスにデフォルトで入れておくメッセージ
**buttons**：ボタンの表示
**default button 1**：1番目のボタンをデフォルトにする

こんな感じになります。
<img width="532" alt="スクリーンショット 2019-12-03 12.12.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268331/f7f1ac06-d07c-a6dd-8795-5d0c6efeb22f.png">



## なまえあってる？
`nameCheck`という名前の関数として括っています。
nameFlg=$( ~ )という部分で`nameInput`でユーザーが入力した`name`という変数を表示して、確認を促しています。
`EOF`と`EOF`の間に記述されているのがApple Script部分となります。

```shell:なまえあってる？.sh
nameChack () {
nameFlg=$(osascript << EOF
display dialog "あなたのお名前は ${name} で間違いないですか？"  with title "じゃんけんゲーム" with text buttons {"いいえ","はい"} default button 2
button returned of result
EOF)
}
```

変数を利用する場合は`${}`を使用します。
他の部分は説明済みのため割愛します。
こんな感じになります。
<img width="532" alt="スクリーンショット 2019-12-03 12.17.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268331/3a9d89f4-2491-65b9-df50-47da472b610e.png">

## どのてをだします？
`selectGCP`という名前の関数として括っています。(~~Google Cloud Platformではない~~)
select=$( ~ )という部分で`nameInput`でユーザーが入力した`name`さんに"グー","チョキ","パー"の3つの中から1つ選んでもらい、その結果を返しています。
また、選ばれた"グー","チョキ","パー"をそれぞれ、0,1,2と置き換えて`userChoice`に入れています。(勝敗の計算に使用するため)

```shell:どのてをだします？.sh
selectGCP () {
select=$(osascript << EOF
display dialog "${name} さんはどの手を出しますか？"  with title "じゃんけんゲーム" buttons{"グー","チョキ","パー"}
button returned of result
EOF)
if [ $select = "グー" ]
  then
    userChoice=0
  elif [[ $select = "チョキ" ]]
  then userChoice=1
else
  userChoice=2
fi
}
```
こんな感じになります。
<img width="532" alt="スクリーンショット 2019-12-03 12.19.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268331/4be6cbcd-10b3-70be-2ff6-696928a7b3bc.png">
3つまでボタンを使えます。
3つ以上から選択させたい場合は、リスト表示も使えます。
リスト表示の仕方は、おまけとして最後の方に書いてます。

## いざしょうぶ！
`battle`という名前の関数として括っています。
comSelect=$( ~ )という部分でRANDOM関数の結果を返しています。

```shell:いざしょうぶ！.sh
battle () {
comSelect=$(($RANDOM % 3))
if [ $comSelect = 0 ]
  then
    comChoice="グー"
  elif [ $comSelect = 1 ]
    then
      comChoice="チョキ"
  else
    comChoice="パー"
fi
result=$((comSelect - userChoice))
battleResult=$(if [ $result -eq 1 ] || [ $result -eq -2 ]
  then
    osascript << EOT
    display dialog "あなたの手：${select} \nvs \nCOMの手：${comChoice} \n\nやるやん。明日は俺にリベンジさせて。"  with title "じゃんけんゲーム" with text buttons {"おわる","もう一回！"} default button 2
button returned of result
EOT
elif [ $result -eq -1 ] || [ $result -eq 2 ]
  then
    osascript << EOT
    display dialog "あなたの手：${select} \nvs \nCOMの手：${comChoice} \n\n俺の勝ち！\nなんで負けたか、明日まで考えといてください。\nそしたら何かが見えてくるはずです。"  with title "じゃんけんゲーム" with text buttons {"おわる","もう一回！"} default button 2
button returned of result
EOT
else
  osascript << EOT
  display dialog "あなたの手：${select} \nvs \nCOMの手：${comChoice} \n\nあいこは負けと一緒。"  with title "じゃんけんゲーム" with text buttons {"おわる","もう一回！"} default button 2
button returned of result
EOT
fi)
}
```

勝負の結果で表示される文言は[本田とじゃんけん](https://dic.nicovideo.jp/a/%23本田とじゃんけん)からまるパクしてます。
こんな感じです。

<img width="532" alt="スクリーンショット 2019-12-03 12.34.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268331/80e91c10-a0da-644e-72f5-40be032a9eb6.png">
<img width="532" alt="スクリーンショット 2019-12-03 12.35.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268331/a1031d76-fce4-f816-63e8-e3202e348a28.png">
<img width="532" alt="スクリーンショット 2019-12-03 12.35.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268331/3b8139bb-2f9b-8e29-b1eb-31890c14c071.png">


## 実行部分

```shell:じゃんけん.sh

doOrNotCheck

if [ $doOrNot = "いいえ" ]
#やらないの・・・
  then
    osascript -e 'display dialog "ケチ！" buttons {"(´･ω･`)"} with icon 2 with title "じゃんけんゲーム" '
  exit
else
  nameInput
  nameChack
  while [ $nameFlg != "はい" ]
  do
    nameInput
    nameChack
  done
fi

selectGCP
battle

while [ $battleResult != "おわる" ]
do
  selectGCP
  battle
done
```

以上、ここまでに紹介したものを上からすべて一つのshファイルに記述することで、じゃんけんができるようになります！

## (おまけ)4つ以上から選択させるやつ

```shell:たくさんからえらぶ.sh
osascript -e 'display dialog choose from list {"グー", "チョキ", "パー","ダイナマイト", "ピストル", "つよいやつ","めっちゃ強いやつ"}'
```

こんな感じ。
<img width="452" alt="スクリーンショット 2019-12-03 17.41.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268331/14840104-05d4-725c-3676-416db6d2d82d.png">


# おわりに
かなりざっくり書いてしまっているのでわかりにくかったらすいません。
ユーザーの環境による値があるものだったり、特定の内容をAPIに飛ばしたり、いろいろできるのではないでしょうか。多分。