シェルスクリプト:四目並べ(Connect Four)ゲーム
シェルスクリプトは、システム管理だけでなく、テキストベースのゲーム作成にも活用できる強力なツールです。ここでは、シェルスクリプトを使って「四目並べ(Connect Four)ゲーム」を作成し、その手順と詳細な解説を行います。四目並べは、縦6行×横7列のグリッドで行われる2人用のボードゲームで、縦・横・斜めのいずれかに自分の色のコマを4つ並べた方が勝利します。この演習を通じて、シェルスクリプトの基本的な構文、配列の操作、条件分岐、ループ、ユーザー入力の処理などの知識を総合的に学ぶことができます。
ゲームの概要
ゲームの目的
- 自分のコマを縦・横・斜めのいずれかに4つ連続して並べることを目指します。
ゲームのルール
- ゲームの進行
・プレイヤーとコンピュータは交互にターンを行います。
・各ターンで、プレイヤーは列を選択し、自分のコマをその列の最も下の空いているマスに配置します。
・グリッドは縦6行×横7列で構成されています。 - 勝利条件
・自分のコマを縦・横・斜めのいずれかに4つ連続して並べると勝利となります。
・全てのマスが埋まっても勝者がいない場合は引き分けです。
connect_four.sh
の作成から実行までの手順と解説
ステップ1:スクリプトファイルの作成
ターミナルで以下のコマンドを実行し、新しいスクリプトファイル connect_four.sh
を作成します。
user01@ubuntu:~$ nano connect_four.sh
ステップ2:スクリプトの内容を記述
エディタが開いたら、以下のコードをコピーして貼り付けます。
#!/bin/bash
# ボードの初期化
initialize_board() {
for ((i=0; i<6; i++)); do
for ((j=0; j<7; j++)); do
board[$i,$j]="."
done
done
}
# ボードの表示
display_board() {
echo " 0 1 2 3 4 5 6"
for ((i=0; i<6; i++)); do
for ((j=0; j<7; j++)); do
echo -n " ${board[$i,$j]}"
done
echo
done
}
# コマを配置する
place_disk() {
local column=$1
local player=$2
for ((i=5; i>=0; i--)); do
if [ "${board[$i,$column]}" == "." ]; then
board[$i,$column]=$player
last_row=$i
last_col=$column
return 0
fi
done
return 1 # 列が埋まっている
}
# 勝利の確認
check_winner() {
local player=$1
local directions=(
"0 1" # 横方向
"1 0" # 縦方向
"1 1" # 斜め右下
"1 -1" # 斜め左下
)
for dir in "${directions[@]}"; do
dx=${dir% *}
dy=${dir#* }
count=1
for ((k=1; k<4; k++)); do
nx=$((last_row + dx * k))
ny=$((last_col + dy * k))
if [ $nx -ge 0 ] && [ $nx -lt 6 ] && [ $ny -ge 0 ] && [ $ny -lt 7 ] && [ "${board[$nx,$ny]}" == "$player" ]; then
count=$((count + 1))
else
break
fi
done
for ((k=1; k<4; k++)); do
nx=$((last_row - dx * k))
ny=$((last_col - dy * k))
if [ $nx -ge 0 ] && [ $nx -lt 6 ] && [ $ny -ge 0 ] && [ $ny -lt 7 ] && [ "${board[$nx,$ny]}" == "$player" ]; then
count=$((count + 1))
else
break
fi
done
if [ $count -ge 4 ]; then
return 0 # 勝利
fi
done
return 1 # 勝利ではない
}
# ボードが満杯か確認
is_board_full() {
for ((j=0; j<7; j++)); do
if [ "${board[0,$j]}" == "." ]; then
return 1 # まだ空きがある
fi
done
return 0 # 満杯
}
# メインゲームループ
declare -A board
initialize_board
current_player="X" # プレイヤーは "X"
computer_player="O" # コンピュータは "O"
while true; do
display_board
while true; do
read -p "コマを落とす列を選んでください(0〜6): " column
if ! [[ "$column" =~ ^[0-6]$ ]]; then
echo "無効な入力です。0〜6の数字を入力してください。"
continue
fi
place_disk "$column" "$current_player"
if [ $? -eq 0 ]; then
break
else
echo "その列は満杯です。別の列を選んでください。"
fi
done
check_winner "$current_player"
if [ $? -eq 0 ]; then
display_board
echo "おめでとうございます!あなたの勝ちです!"
exit
fi
is_board_full
if [ $? -eq 0 ]; then
display_board
echo "引き分けです!"
exit
fi
# コンピュータのターン
echo "コンピュータのターンです。"
sleep 1
while true; do
column=$((RANDOM % 7))
place_disk "$column" "$computer_player"
if [ $? -eq 0 ]; then
echo "コンピュータは列 $column にコマを落としました。"
break
fi
done
check_winner "$computer_player"
if [ $? -eq 0 ]; then
display_board
echo "残念!コンピュータの勝ちです。"
exit
fi
is_board_full
if [ $? -eq 0 ]; then
display_board
echo "引き分けです!"
exit
fi
done
ステップ3:スクリプトの内容の解説
1.シェバン行
#!/bin/bash
- スクリプトが Bash シェルで実行されることを指定します。
2.ボードの初期化関数 initialize_board
initialize_board() {
for ((i=0; i<6; i++)); do
for ((j=0; j<7; j++)); do
board[$i,$j]="."
done
done
}
- 目的:6行×7列のボードを初期化し、全てのマスを
"."
(空きマス)で埋めます。 - 解説:
・二重ループで全てのマスを初期化します。
・ボードは連想配列board
を使用して管理します。
3.ボードの表示関数 display_board
display_board() {
echo " 0 1 2 3 4 5 6"
for ((i=0; i<6; i++)); do
for ((j=0; j<7; j++)); do
echo -n " ${board[$i,$j]}"
done
echo
done
}
- 目的:現在のボードの状態を表示します。
- 解説:列番号を表示し、視覚的にボードの状態を確認できます。
4.コマを配置する関数 place_disk
place_disk() {
local column=$1
local player=$2
for ((i=5; i>=0; i--)); do
if [ "${board[$i,$column]}" == "." ]; then
board[$i,$column]=$player
last_row=$i
last_col=$column
return 0
fi
done
return 1 # 列が埋まっている
}
- 目的:指定した列にコマを配置します。
- 解説:
・下から上に向かって空きマスを探し、最も下の空きマスにコマを配置します。
・配置した位置をlast_row
とlast_col
に保存します。
・列が満杯の場合はエラーを返します。
5.勝利の確認関数 check_winner
check_winner() {
local player=$1
local directions=(
"0 1" # 横方向
"1 0" # 縦方向
"1 1" # 斜め右下
"1 -1" # 斜め左下
)
for dir in "${directions[@]}"; do
dx=${dir% *}
dy=${dir#* }
count=1
# 正方向のチェック
# 逆方向のチェック
if [ $count -ge 4 ]; then
return 0 # 勝利
fi
done
return 1 # 勝利ではない
}
- 目的:最後に置いたコマから、縦・横・斜めに4つ連続したコマがあるかを確認します。
- 解説:
・4つの方向を定義し、各方向に対して同じ色のコマが連続しているかを調べます。
・count
が4以上になれば勝利です。
6.ボードが満杯か確認する関数 is_board_full
is_board_full() {
for ((j=0; j<7; j++)); do
if [ "${board[0,$j]}" == "." ]; then
return 1 # まだ空きがある
fi
done
return 0 # 満杯
}
- 目的:ボードに空きがあるかを確認します。
- 解説:最上段のマスに空きがあるかを調べ、空きがなければボードは満杯です。
7.メインゲームループ
declare -A board
initialize_board
current_player="X" # プレイヤーは "X"
computer_player="O" # コンピュータは "O"
while true; do
# プレイヤーのターン
# 勝利と引き分けの確認
# コンピュータのターン
# 勝利と引き分けの確認
done
解説
- ゲームが終了するまで、プレイヤーとコンピュータのターンを繰り返します。
- 各ターンでコマを配置し、勝利または引き分けを確認します。
- コンピュータはランダムに列を選択します。
ステップ4:スクリプトに実行権限を付与
スクリプトを保存してエディタを終了したら、実行権限を付与します。
user01@ubuntu:~$ chmod +x connect_four.sh
ステップ5:スクリプトの実行
スクリプトを実行して、四目並べゲームを開始します。
user01@ubuntu:~$ ./connect_four.sh
実行例
0 1 2 3 4 5 6
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
コマを落とす列を選んでください(0〜6): 3
コンピュータのターンです。
コンピュータは列 5 にコマを落としました。
0 1 2 3 4 5 6
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . X . O .
コマを落とす列を選んでください(0〜6):
解説
- プレイヤーは 0〜6 の数字で列を選択し、コマを配置します。
- コンピュータはランダムに列を選択してコマを配置します。
- 勝利または引き分けになるとゲームが終了し、結果が表示されます。
ここで作成したファイルの削除
ゲームのテストが終了したら、作成した connect_four.sh
ファイルを削除します。
user01@ubuntu:~$ rm connect_four.sh
まとめ
- シェルスクリプトの応用:四目並べゲームを通じて、シェルスクリプトでのゲーム作成方法を学びました。
- 配列の操作:二次元配列を使用してボードを管理し、効率的にデータを扱いました。
- 条件分岐とループ:
if
文やwhile
ループを使って、ゲームの進行とロジックを制御しました。 - ユーザー入力の処理:
read
コマンドを使用してユーザーの入力を受け取り、入力のバリデーションを行いました。 - 関数の活用:関連する処理を関数としてまとめ、コードの再利用性と可読性を向上させました。
- ゲームロジックの実装:四目並べのルールに基づくロジックをシェルスクリプトで実装しました。
シェルスクリプトは、システム管理以外にも多くの用途で活用できます。今回の四目並べゲームを基に、コンピュータのAIを強化したり、GUIを導入したり、ボードサイズを変更したりして、さらなる機能拡張に挑戦してみてください。