
シェルスクリプト:マスターマインドゲーム
シェルスクリプトは、システム管理やタスクの自動化だけでなく、簡単なゲームやツールを作成するための強力なツールです。ここでは、シェルスクリプトを使って「マスターマインドゲーム」を作成し、その手順と詳細な解説を行います。このゲームを通じて、シェルスクリプトの基本的な構文、配列の操作、関数の定義、ループ、条件分岐、入力のバリデーションなど、さまざまなスクリプトのテクニックを学ぶことができます。

マスターマインドゲームの概要
- 目的:コンピューターがランダムに選んだ4桁の数字を、ユーザーが推測して当てるゲームです。
- ルール:
・コンピューターは1から6までの数字を使って、重複しない4桁の数字を生成します。
・ユーザーは4桁の数字を入力して推測します。
・各試行ごとに、以下のフィードバックが与えられます:
・ヒット:数字と位置の両方が正しい数。
・ブロー:数字は正しいが、位置が間違っている数。
・ユーザーはフィードバックをもとに、制限回数内に正解を当てることを目指します。
フィードバックの例
| ユーザーの推測 | ヒット | ブロー | フィードバックの意味 |
|---|---|---|---|
| 1234 | 1 | 2 | 1つの数字が位置も数字も正しく、2つの数字が位置は間違いだが数字は正しい |
| 1356 | 0 | 3 | 正しい数字が3つあるが、全て位置が間違っている |
| 2465 | 2 | 0 | 2つの数字が位置も数字も正しい |
スクリプトの作成から実行までの手順と解説
ステップ1:スクリプトファイルの作成
ターミナルで以下のコマンドを実行し、新しいスクリプトファイル mastermind.sh を作成します。
user01@ubuntu:~$ nano mastermind.shステップ2:スクリプトの内容を記述
エディタが開いたら、以下のコードをコピーして貼り付けます。
#!/bin/bash
# 1から6の数字を使って、重複なしの4桁の数字を生成
generate_secret() {
numbers=(1 2 3 4 5 6)
secret=()
for i in {1..4}; do
index=$((RANDOM % ${#numbers[@]}))
secret+=("${numbers[$index]}")
unset 'numbers[$index]'
numbers=("${numbers[@]}")
done
}
# ヒットとブローを計算
calculate_hit_blow() {
local guess=("$@")
hit=0
blow=0
for i in {0..3}; do
if [ "${guess[$i]}" -eq "${secret[$i]}" ]; then
hit=$((hit + 1))
elif [[ " ${secret[@]} " =~ " ${guess[$i]} " ]]; then
blow=$((blow + 1))
fi
done
}
# ゲームの開始
generate_secret
attempts=0
max_attempts=10
echo "マスターマインドゲームへようこそ!1から6の数字を使った重複なしの4桁の数字を当ててください。"
echo "あなたには合計 $max_attempts 回の試行があります。"
# メインゲームループ
while [ $attempts -lt $max_attempts ]; do
attempts=$((attempts + 1))
while true; do
read -p "推測を入力してください(例:1234): " input
# 入力のバリデーション
if [[ ! "$input" =~ ^[1-6]{4}$ ]]; then
echo "エラー: 1から6の数字を使った4桁の数字を入力してください。"
continue
fi
# 重複チェック
unique_check=$(echo "$input" | grep -o . | sort | uniq -d)
if [ -n "$unique_check" ]; then
echo "エラー: 数字は重複しないようにしてください。"
continue
fi
break
done
# ヒットとブローの計算
guess=($(echo "$input" | grep -o .))
calculate_hit_blow "${guess[@]}"
if [ $hit -eq 4 ]; then
echo "おめでとうございます!正解を当てました。"
break
else
echo "ヒット: $hit, ブロー: $blow"
echo "残り試行回数: $((max_attempts - attempts))"
fi
done
if [ $hit -ne 4 ]; then
echo "ゲームオーバー。正解は ${secret[@]} でした。"
fiステップ3:スクリプトの内容の解説
1.シェバン行
#!/bin/bash- スクリプトが Bash シェルで実行されることを指定します。
2.秘密の数字を生成する関数
generate_secret() {
numbers=(1 2 3 4 5 6)
secret=()
for i in {1..4}; do
index=$((RANDOM % ${#numbers[@]}))
secret+=("${numbers[$index]}")
unset 'numbers[$index]'
numbers=("${numbers[@]}")
done
}目的:1から6の数字を使って、重複しない4桁の秘密の数字を生成します。
解説
numbers配列に1から6の数字を格納します。- ループを4回繰り返し、各回で以下を行います。
・RANDOM % ${#numbers[@]}でnumbers配列の範囲内でランダムなインデックスを生成します。
・secret配列に選ばれた数字を追加します。
・unsetコマンドで選ばれた数字をnumbers配列から削除し、重複を避けます。
3.ヒットとブローを計算する関数
calculate_hit_blow() {
local guess=("$@")
hit=0
blow=0
for i in {0..3}; do
if [ "${guess[$i]}" -eq "${secret[$i]}" ]; then
hit=$((hit + 1))
elif [[ " ${secret[@]} " =~ " ${guess[$i]} " ]]; then
blow=$((blow + 1))
fi
done
}目的:ユーザーの推測と秘密の数字を比較し、ヒットとブローの数を計算します。
解説
guess配列にユーザーの入力を格納します。- 0から3までのループで各桁を比較します。
・同じ位置で数字が一致すればhitをカウントアップ。
・数字が秘密の数字に含まれていれば(位置は異なる)、blowをカウントアップ。
4.ゲームの開始と変数の初期化
generate_secret
attempts=0
max_attempts=10
echo "マスターマインドゲームへようこそ!1から6の数字を使った重複なしの4桁の数字を当ててください。"
echo "あなたには合計 $max_attempts 回の試行があります。"解説
generate_secret関数を呼び出して、秘密の数字を生成します。attemptsは現在の試行回数を示し、初期値は0です。max_attemptsはユーザーが推測できる最大回数です。- ゲームのルールと試行回数をユーザーに表示します。
5.メインゲームループ
while [ $attempts -lt $max_attempts ]; do
attempts=$((attempts + 1))
while true; do
read -p "推測を入力してください(例:1234): " input
# 入力のバリデーション
if [[ ! "$input" =~ ^[1-6]{4}$ ]]; then
echo "エラー: 1から6の数字を使った4桁の数字を入力してください。"
continue
fi
# 重複チェック
unique_check=$(echo "$input" | grep -o . | sort | uniq -d)
if [ -n "$unique_check" ]; then
echo "エラー: 数字は重複しないようにしてください。"
continue
fi
break
done
# ヒットとブローの計算
guess=($(echo "$input" | grep -o .))
calculate_hit_blow "${guess[@]}"
if [ $hit -eq 4 ]; then
echo "おめでとうございます!正解を当てました。"
break
else
echo "ヒット: $hit, ブロー: $blow"
echo "残り試行回数: $((max_attempts - attempts))"
fi
done解説
試行回数が最大試行回数に達するまでループを続けます。
- ユーザー入力のバリデーション
・正規表現^[1-6]{4}$を使用して、1から6の数字4桁であることを確認します。
・grepとuniqを使って、数字が重複していないかをチェックします。 - ヒットとブローの計算
・ユーザーの入力を1文字ずつ分割してguess配列に格納します。
・calculate_hit_blow関数を呼び出して、ヒットとブローを計算します。 - 結果の表示
・ヒットが4であれば、ユーザーの勝利としてゲームを終了します。
・そうでなければ、ヒットとブローの数、および残りの試行回数を表示します。
6.ゲームオーバーの判定
if [ $hit -ne 4 ]; then
echo "ゲームオーバー。正解は ${secret[@]} でした。"
fi解説
最大試行回数に達してもヒットが4にならなかった場合、ゲームオーバーとして正解を表示します。
ステップ4:スクリプトに実行権限を付与
スクリプトを保存してエディタを閉じたら、実行権限を付与します。
user01@ubuntu:~$ chmod +x mastermind.shステップ5:スクリプトの実行
スクリプトを実行して、マスターマインドゲームを開始します。
user01@ubuntu:~$ ./mastermind.sh実行例
マスターマインドゲームへようこそ!1から6の数字を使った重複なしの4桁の数字を当ててください。
あなたには合計 10 回の試行があります。
推測を入力してください(例:1234): 1234
ヒット: 1, ブロー: 2
残り試行回数: 9
推測を入力してください(例:1234): 1456
ヒット: 2, ブロー: 1
残り試行回数: 8
推測を入力してください(例:1234): 1546
おめでとうございます!正解を当てました。解説
- ユーザーの推測:ユーザーは重複しない1から6の数字4桁を入力します。
- フィードバック:ヒットとブローの数が表示されます。
- 推測の繰り返し:フィードバックをもとに、ユーザーは次の推測を行います。
- ゲームの終了:ヒットが4になるとゲームに勝利します。最大試行回数に達するとゲームオーバーです。
ここで作成したファイルの削除
演習が終了したら、作成した mastermind.sh ファイルを削除します。
user01@ubuntu:~$ rm mastermind.shまとめ
- シェルスクリプトの応用:マスターマインドゲームを通じて、シェルスクリプトでのゲーム作成方法を学びました。
- 配列の操作:配列を使って秘密の数字やユーザーの推測を管理し、効率的なデータ処理を行いました。
- 関数の定義と活用:再利用可能なコードを関数として定義し、コードの可読性と保守性を向上させました。
- 入力のバリデーション:正規表現やコマンドを使って、ユーザーの入力が正しい形式であるかを確認しました。
- ループと条件分岐:
whileループやif文を使って、ゲームの進行と終了条件を制御しました。 - 文字列操作とコマンドの活用:
grep、sort、uniqなどのコマンドを使って、文字列の解析や重複チェックを行いました。
シェルスクリプトは、システム管理以外にも多くの用途で活用できます。今回のマスターマインドゲームを基に、数字の範囲や桁数を変更したり、難易度を調整したり、GUI を導入したりして、さらなる機能拡張に挑戦してみてください。
