シェルスクリプト:ヤッツィーゲーム
ヤッツィーは、5つのサイコロを使って特定の組み合わせを作り、高得点を目指すダイスゲームです。ここでは、シェルスクリプトでヤッツィーゲームを作成し、その手順と詳細な解説を行います。このゲームを通じて、シェルスクリプトの配列操作、関数の定義、条件分岐、ループ、ユーザー入力の処理などの知識を深めることができます。
ヤッツィーゲームの概要
ゲームの目的
- サイコロを振って特定の役を作り、可能な限り高い得点を獲得することを目指します。
ゲームのルール
ゲームの進行
- プレイヤーは5つのサイコロを3回まで振ることができます。
- 各ターンで、保持するサイコロと再度振るサイコロを選択できます。
- 振り終わった後、得点表の未使用の項目に得点を記録します。
得点表の項目
項目 | 説明 | 最大得点 |
---|---|---|
エース(1の目) | 1の目の合計 | 5 |
ツー(2の目) | 2の目の合計 | 10 |
スリー(3の目) | 3の目の合計 | 15 |
フォー(4の目) | 4の目の合計 | 20 |
ファイブ(5の目) | 5の目の合計 | 25 |
シックス(6の目) | 6の目の合計 | 30 |
3カード | 同じ目が3つ以上で、サイコロの合計 | 30 |
4カード | 同じ目が4つ以上で、サイコロの合計 | 30 |
フルハウス | 同じ目が3つと2つで、25点 | 25 |
スモールストレート | 4つの連続した目で、30点 | 30 |
ラージストレート | 5つの連続した目で、40点 | 40 |
ヤッツィー | 同じ目が5つで、50点 | 50 |
チャンス | サイコロの合計 | 30 |
勝利条件
- 全ての項目に得点を記入した後、合計得点が最も高いプレイヤーが勝利します。
- このシェルスクリプトでは、プレイヤーが最高得点を目指すシングルプレイとなります。
yahtzee.sh
の作成から実行までの手順と解説
ステップ1:スクリプトファイルの作成
ターミナルで以下のコマンドを実行し、新しいスクリプトファイルyahtzee.sh
を作成します。
user01@ubuntu:~$ nano yahtzee.sh
ステップ2:スクリプトの内容を記述
エディタが開いたら、以下のコードをコピーして貼り付けます。
#!/bin/bash
# サイコロを振る関数
roll_dice() {
dice=()
for ((i=0; i<5; i++)); do
dice+=($((RANDOM % 6 + 1)))
done
}
# サイコロを再度振る関数
reroll_dice() {
local indices=("$@")
for index in "${indices[@]}"; do
dice[$index]=$((RANDOM % 6 + 1))
done
}
# サイコロの表示
display_dice() {
echo "現在のサイコロ: ${dice[@]}"
}
# 得点を計算する関数
calculate_score() {
local category=$1
local counts=()
for ((i=1; i<=6; i++)); do
counts[$i]=0
done
for die in "${dice[@]}"; do
((counts[$die]++))
done
case $category in
"1") echo $((counts[1] * 1)) ;;
"2") echo $((counts[2] * 2)) ;;
"3") echo $((counts[3] * 3)) ;;
"4") echo $((counts[4] * 4)) ;;
"5") echo $((counts[5] * 5)) ;;
"6") echo $((counts[6] * 6)) ;;
"3kind")
for count in "${counts[@]}"; do
if [ "$count" -ge 3 ]; then
echo $(( ${dice[0]} + ${dice[1]} + ${dice[2]} + ${dice[3]} + ${dice[4]} ))
return
fi
done
echo 0
;;
"4kind")
for count in "${counts[@]}"; do
if [ "$count" -ge 4 ]; then
echo $(( ${dice[0]} + ${dice[1]} + ${dice[2]} + ${dice[3]} + ${dice[4]} ))
return
fi
done
echo 0
;;
"fullhouse")
if [[ " ${counts[@]} " =~ " 2 " ]] && [[ " ${counts[@]} " =~ " 3 " ]]; then
echo 25
else
echo 0
fi
;;
"smallstraight")
straights=("1234" "2345" "3456")
dice_str=$(printf "%s\n" "${dice[@]}" | sort -n | uniq | tr -d '\n')
for straight in "${straights[@]}"; do
if [[ "$dice_str" == *"$straight"* ]]; then
echo 30
return
fi
done
echo 0
;;
"largestraight")
straights=("12345" "23456")
dice_str=$(printf "%s\n" "${dice[@]}" | sort -n | uniq | tr -d '\n')
for straight in "${straights[@]}"; do
if [[ "$dice_str" == "$straight" ]]; then
echo 40
return
fi
done
echo 0
;;
"yahtzee")
for count in "${counts[@]}"; do
if [ "$count" -eq 5 ]; then
echo 50
return
fi
done
echo 0
;;
"chance")
echo $(( ${dice[0]} + ${dice[1]} + ${dice[2]} + ${dice[3]} + ${dice[4]} ))
;;
*)
echo 0
;;
esac
}
# 得点表の初期化
declare -A scorecard
categories=("1" "2" "3" "4" "5" "6" "3kind" "4kind" "fullhouse" "smallstraight" "largestraight" "yahtzee" "chance")
for category in "${categories[@]}"; do
scorecard[$category]=""
done
# ゲーム開始
echo "=== ヤッツィーゲームへようこそ! ==="
for turn in {1..13}; do
echo "ターン $turn/13"
roll_dice
display_dice
for roll in {1..2}; do
read -p "再度振りたいサイコロの番号をスペースで区切って入力(例: 0 2 4)、振らない場合はnを入力: " input
if [ "$input" == "n" ]; then
break
else
indices=($input)
reroll_dice "${indices[@]}"
display_dice
fi
done
echo "得点表:"
for category in "${categories[@]}"; do
if [ -z "${scorecard[$category]}" ]; then
echo "$category: 未使用"
else
echo "$category: ${scorecard[$category]}"
fi
done
while true; do
read -p "得点を記入するカテゴリーを選んでください: " chosen_category
if [ -z "${scorecard[$chosen_category]}" ]; then
score=$(calculate_score "$chosen_category")
scorecard[$chosen_category]=$score
echo "カテゴリー '$chosen_category' に $score 点を記入しました。"
break
else
echo "そのカテゴリーは既に使用されています。別のカテゴリーを選んでください。"
fi
done
done
# 合計得点の計算
total_score=0
for score in "${scorecard[@]}"; do
total_score=$((total_score + score))
done
echo "ゲーム終了!あなたの合計得点は $total_score 点です!お疲れ様でした!"
ステップ3:スクリプトの内容の解説
1.シェバン行
#!/bin/bash
- 目的:スクリプトがBashシェルで実行されることを指定します。
2.サイコロを振る関数 roll_dice
roll_dice() {
dice=()
for ((i=0; i<5; i++)); do
dice+=($((RANDOM % 6 + 1)))
done
}
- 目的:5つのサイコロを振り、結果を
dice
配列に格納します。 - 解説:
RANDOM % 6 + 1
:1から6までのランダムな数字を生成します。
3.サイコロを再度振る関数 reroll_dice
reroll_dice() {
local indices=("$@")
for index in "${indices[@]}"; do
dice[$index]=$((RANDOM % 6 + 1))
done
}
- 目的:指定したインデックスのサイコロを再度振ります。
- 解説:ユーザーが入力したサイコロの位置を受け取り、そのサイコロを新しい値に更新します。
4.サイコロの表示関数 display_dice
display_dice() {
echo "現在のサイコロ: ${dice[@]}"
}
- 目的:現在のサイコロの目を表示します。
5.得点を計算する関数 calculate_score
calculate_score() {
# カテゴリーに応じて得点を計算し、返します。
}
- 目的:指定したカテゴリーに基づいて、現在のサイコロから得点を計算します。
- 解説:
・サイコロの目の出現回数をcounts
配列に格納します。
・case
文でカテゴリーごとに計算ロジックを実装します。
6.得点表の初期化
declare -A scorecard
categories=("1" "2" "3" "4" "5" "6" "3kind" "4kind" "fullhouse" "smallstraight" "largestraight" "yahtzee" "chance")
for category in "${categories[@]}"; do
scorecard[$category]=""
done
- 目的:得点表を連想配列
scorecard
で管理し、初期化します。 - 解説:各カテゴリーをキーとし、得点を値として格納します。
7.ゲームのメインループ
for turn in {1..13}; do
# 各ターンの処理を行います。
done
解説
- ゲームは13ターンで構成されます。
- 各ターンでサイコロを振り、最大2回まで再度振ることができます。
- 最後に得点を得点表に記入します。
8.サイコロの再度振りの処理
for roll in {1..2}; do
read -p "再度振りたいサイコロの番号を... "
# ユーザーの入力に応じてサイコロを再度振ります。
done
解説
- ユーザーが再度振りたいサイコロの番号を入力します。
n
を入力すると、再度振りをスキップします。
9.得点の記入
while true; do
read -p "得点を記入するカテゴリーを選んでください: " chosen_category
if [ -z "${scorecard[$chosen_category]}" ]; then
score=$(calculate_score "$chosen_category")
scorecard[$chosen_category]=$score
echo "カテゴリー '$chosen_category' に $score 点を記入しました。"
break
else
echo "そのカテゴリーは既に使用されています。別のカテゴリーを選んでください。"
fi
done
解説
- ユーザーが得点を記入したいカテゴリーを選択します。
- 既に使用済みのカテゴリーは選択できません。
10.合計得点の計算と表示
total_score=0
for score in "${scorecard[@]}"; do
total_score=$((total_score + score))
done
echo "ゲーム終了!あなたの合計得点は $total_score 点です!お疲れ様でした!"
- 目的:ゲーム終了後に合計得点を計算し、表示します。
ステップ4:スクリプトに実行権限を付与
スクリプトを保存してエディタを終了したら、以下のコマンドで実行権限を付与します。
user01@ubuntu:~$ chmod +x yahtzee.sh
ステップ5:スクリプトの実行
スクリプトを実行して、ヤッツィーゲームを開始します。
user01@ubuntu:~$ ./yahtzee.sh
実行例
=== ヤッツィーゲームへようこそ! ===
ターン 1/13
現在のサイコロ: 2 5 3 6 1
再度振りたいサイコロの番号をスペースで区切って入力(例: 0 2 4)、振らない場合はnを入力: 1 3
現在のサイコロ: 2 4 3 2 1
再度振りたいサイコロの番号をスペースで区切って入力(例: 0 2 4)、振らない場合はnを入力: n
得点表:
1: 未使用
2: 未使用
3: 未使用
4: 未使用
5: 未使用
6: 未使用
3kind: 未使用
4kind: 未使用
fullhouse: 未使用
smallstraight: 未使用
largestraight: 未使用
yahtzee: 未使用
chance: 未使用
得点を記入するカテゴリーを選んでください: 2
カテゴリー '2' に 4 点を記入しました。
...
(同様にターンが進行します)
解説
- ユーザーはサイコロを振り、再度振りたいサイコロを選択します。
- 得点を記入するカテゴリーを選び、得点表を埋めていきます。
- 13ターン終了後、合計得点が表示されます。
ここで作成したファイルの削除
ゲームのテストが終了したら、作成したyahtzee.sh
ファイルを削除します。
user01@ubuntu:~$ rm yahtzee.sh
まとめ
- シェルスクリプトの応用:ヤッツィーゲームを通じて、シェルスクリプトでのゲーム開発手法を学びました。
- 配列の操作:サイコロや得点表を配列で管理し、データの操作を効率的に行いました。
- 関数の活用:機能ごとに関数を定義し、コードの再利用性と可読性を向上させました。
- 条件分岐とループ:
if
文やfor
ループを駆使して、ゲームのロジックを制御しました。 - ユーザー入力の処理:
read
コマンドでユーザーからの入力を取得し、バリデーションを行いました。 - ゲームロジックの実装:ヤッツィーの複雑な得点計算やルールをシェルスクリプトで実装しました。
シェルスクリプトはシステム管理だけでなく、さまざまな用途で活用できます。今回のヤッツィーゲームを基に、コンピュータとの対戦モードを追加したり、スコアの保存機能を実装したりして、さらなる機能拡張に挑戦してみてください。