7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Windows】Bash でスロットゲームを作ってみた

Last updated at Posted at 2021-09-02

動機・環境

Linux のコマンドに慣れるために、ちょっと遊びで、シェルスクリプト(Bash)でスロットゲームを作成しました。本来ならシェルスクリプトでやるようなことではないかもしれませんが、その辺はご愛敬ということで。
環境は WSL(ubuntu 20-04) です。
間違いやお気づきの点などございましたら、ご指摘いただけると幸いです。

こんな感じのゲームです。
slot.gif 

コード(Bash)

#!/bin/bash

########################
# スロットゲーム
# 作成日 2021/07/03
# ver. 0.0.4 2022/05/24
########################

# カーソル非表示
printf "\e[?25l"

# ANSIエスケープシーケンスリセット
esc_reset() {
 printf "\e[2J\e[H\e[?25h"
 exit 1
}
trap "esc_reset" INT QUIT TERM

# 乱数生成
random_card() {
 cards=(7 \$ ?)
 card="${cards[$((RANDOM % 3))]}"
 printf "%s" $card
}

# スロット画面の描画
slot_init() {
 printf "\e[2J\e[H"
 slot_flame="***********"
 show_cards="*[|$(random_card)|$(random_card)|$(random_card)|]*"
 printf "%s\n" "${slot_flame}"
 printf "%s\n" "${show_cards}"
 printf "%s\n" "${slot_flame}"
}

slot_init

# ゲームスタート
game_start_end() {
 while :
 do
   read -p "$1" key
   case "$key" in
     [Yy]*)
       break
       ;;
     [Nn]*)
       printf "\e[?25h"
       exit 0
       ;;
     *)
       echo "y または n を入力してください!"
       ;;
   esac
 done
}
printf "\e[5;1H"
msg="ゲームを始めますか? [y/n]: "
game_start_end "$msg"

# Enterキーカウント
trapped() {
 enter_count=$((enter_count + 1))
}

# ゲームの判定
slot_judge() {
   c1="\e[32m"; c2="\e[30;46m"; ce="\e[m"
   case "$enter_count" in
     0)
       card_1=$(random_card)
       card_2=$(random_card)
       card_3=$(random_card)
       show_cards="*[|${card_1}|${card_2}|${card_3}|]*"
       printf "\e[2;1H%s\e[1G" "${show_cards}"
       ;;
     1)
       card_2=$(random_card)
       card_3=$(random_card)
       printf "\e[2;1H*[|$c1%s$ce|%s|%s|]*\e[1G" ${card_1} ${card_2} ${card_3}
       ;;
     2)
       card_3=$(random_card)
       if [[ "$card_1" == "$card_2" ]]; then
         printf "\e[2;1H*[|$c2%s$ce|$c2%s$ce|%s|]*\e[1G" ${card_1} ${card_2} ${card_3}
       else
         printf "\e[2;1H*[|$c1%s$ce|$c1%s$ce|%s|]*\e[1G" ${card_1} ${card_2} ${card_3}
       fi
       ;;
     3)
       if [[ "$card_1" == "$card_2" && "$card_1" == "$card_3" ]]; then
         success_show
         return
       fi
       if [[ "$card_1" == "$card_2" ]]; then
         printf "\e[2;1H*[|$c2%s$ce|$c2%s$ce|$c1%s$ce|]*\e[1G" ${card_1} ${card_2} ${card_3}
       elif [[ "$card_1" == "$card_3" ]]; then
         printf "\e[2;1H*[|$c2%s$ce|$c1%s$ce|$c2%s$ce|]*\e[1G" ${card_1} ${card_2} ${card_3}
       elif [[ "$card_2" == "$card_3" ]]; then
         printf "\e[2;1H*[|$c1%s$ce|$c2%s$ce|$c2%s$ce|]*\e[1G" ${card_1} ${card_2} ${card_3}
       else
         printf "\e[2;1H*[|$c1%s$ce|$c1%s$ce|$c1%s$ce|]*\e[1G" ${card_1} ${card_2} ${card_3}
       fi
       printf "\e[5;1H\e[K残念でした!\n"
       return
       ;;
     *)
       printf "\e[5;1H\e[?25hAn unexpected error has occurred..." >&2
       kill -KILL $$
       exit 1
       ;;
   esac
}

# スロットのサクセス画面(点滅表示)
display_slot() {
 c1="\e[31m"; c2="\e[30;46m"; ce="\e[m";
 for i in $(seq 8); do
   printf "\e[2J\e[H"
   if ((i % 2 == 0)); then
     printf "\e[1;1H$c1%s$ce" "${slot_flame}"
     printf "\e[3;1H$c1%s$ce" "${slot_flame}"
   fi
   printf "\e[2;1H$c1*$ce[|$c2%s$ce|$c2%s$ce|$c2%s$ce|]$c1*$ce" ${card_1} ${card_2} ${card_3}
   sleep 0.1
 done
 printf "\e[1;1H%s" "${slot_flame}"
 printf "\e[2;1H*[|$c2%s$ce|$c2%s$ce|$c2%s$ce|]*" ${card_1} ${card_2} ${card_3}
 printf "\e[3;1H%s" "${slot_flame}"
}

success_show() {
 display_slot
 printf "\e[5;1Hおめでとうございます!\n"
}

# スロットマシーン作成
slot_machine() {
 enter_count=0
 trap "trapped" USR1 USR2
 trap "slot_init" CONT

 while :
 do
   slot_judge
   if ((enter_count == 3)); then
     return
   fi
   sleep 0.2
 done
}

# トラップ処理
esc_bg_reset() {
 if [[ ${PID:=0} -gt 0 ]]; then
   kill $PID
 fi
 esc_reset
}
trap "esc_bg_reset" QUIT

# ユーザ入力・操作
usr_num=1
first=true
while :
do
 if "$first"; then
   first=false
 else
   printf "\e[5;1H\e[J"
 fi
 slot_machine &
 PID=$!

 for ((i=0; i<3; i++)); do
   while :
   do
     read -s -n 1 key
     if [[ -z $key && ${PID:=0} -gt 0 ]]; then
       if ((usr_num == 1)); then
         kill -USR1 $PID
       else
         kill -USR2 $PID
       fi 
       usr_num=$((usr_num * -1))
       break
     else
       printf "\e[5;1H何も入力せずに、Enterキーを押してください!"
     fi
   done
 done

 wait

 # ゲームの続行・終了
 printf "\e[7;1H"
 msg="もう一度チャレンジしますか? [y/n]: "
 game_start_end "$msg"
done

7
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?