はじめに
初投稿です。
Rubyの学習を始めて1ヶ月弱、オブジェクト指向を取り入れたアウトプットとしてコンソール上で遊べるブラックジャックゲームを作りました。
カードのヒット(引く) or スタンド(引かない)の選択をユーザーの入力から受け取る処理の部分で新しい学びがあったので、似たような学習段階の方々に向けて記事にしました。
概要
- 入力内容が正しい形式であることの確認方法として「入力の検証ループ」を紹介
- ブラックジャックゲームでの実使用例を紹介
※ オブジェクト指向の内容は含みません。反復処理を用いた内容です。
記事内では「入力の検証ループ」と表現しますが、公式の呼び方ではありません。
説明上、端的に表すためにこのように呼んでいます。
気付きまでの経緯
ざっくり
- CLIゲームで入力の受け取り → 想定外の入力に対応しないとな → 例外処理を使う?
- 例外処理は例外的な問題への対応策。誤入力はエラーではないから、今ケースでは過剰かも?
- 入力内容の妥当性をチェックするだけなら「入力の検証ループ」で対応できる
もう少し詳しく
今回作ったブラックジャックのゲーム中にユーザーの入力によって処理を変える部分があり、想定外の入力にどう対応するべきかを考えたことが始まり。
最初は例外処理を使おうと考えたが、例外処理は
- 予期しない状況やエラーが発生した場合にプログラムが適切に処理できるようにする必要がある場合
- 外部リソース(ファイル、データベースなど)へのアクセス中にエラーが発生する可能性がある場合
このようなケースで使われることを想定しており、私の目的にはオーバーな対応策に思えた。
そこでいろいろ調べた結果、たどり着いたのが「入力の検証ループ」。
入力の検証ループ
入力の検証ループとは
ユーザーから「期待通りの妥当な入力」があるまでループを使って再入力を促すもの。
loop
やwhile
などの反復処理を利用して実装する。
言ってみれば
「正しい入力するまで出られません」なループですね。
使い所
- ユーザーからの入力が特定の形式に従っていることを確認する必要があるとき
- 不正な入力が想定されるとき
メリット
- コードがシンプルで可読性、保守性の向上につながる
- if文の条件をメソッドで切り出せば色々な入力チェックに使いまわせる(再利用性向上)
コード例
loop
を用いた例です。
if文の条件をvalid?
メソッドに切り出していますが、ベタ書きでも当然OKです。
また、入力内容を返す必要がない場合はbreak
で抜けてもいいです。
loop do
input = gets.chomp
return input if valid?(input)
puts "入力が無効です。もう一度お試しください。"
end
処理の解説
-
gets
でコンソールから入力を受け取り - if文で判定
- 条件を満たせば、
return
でループを抜ける - 条件を満たさなければ、正しい入力を促すメッセージを出力、その後ループ続行
ブラックジャックゲームでの使用例
コンソール上で入力を促す
※ 以下コンソールの表示例は一部抜粋
あなたの現在の得点は18です。
カードを引きますか?(Y/N)
入力の検証ループ
以下の検証ループをメソッドにして、呼び出し元の別のループを抜けるかどうかの判定用に使いました。
loop do
input = gets.chomp.upcase
return true if input == 'Y'
return false if input == 'N'
puts "入力が正しくありません。'Y' または 'N' を入力してください。"
end
- 入力内容が
YかN
なら検証ループを抜ける- Yなら
true
を返して、呼び出し元のループを続行 - Nなら
false
を返して、呼び出し元のループを抜ける
- Yなら
- 入力内容が
YかN以外
の入力は検証ループを続行
upcase
を使って小文字の入力でも通るようにしてあります。
正しい入力の例
想定通りの入力なので検証ループから抜け、後続の処理が実行されます。
あなたの現在の得点は18です。
カードを引きますか?(Y/N)
n
ディーラーが引いた2枚目のカードはハートの8
誤入力の例
想定外の入力なので、正しい入力をするまでループが回ります。
カードを引きますか?(Y/N)
z
入力が正しくありません。'Y' または 'N' を入力してください。
x
入力が正しくありません。'Y' または 'N' を入力してください。
Y
あなたが引いた3枚目のカードはクローバーの2
おわりに
最後まで読んでいただきありがとうございます。
学び始めの方に少しでも参考になれば幸いです。
ループの練習の1つとしてirb
で試してみてもいいかもしれませんね。
ツッコミどころがありましたら遠慮なくご指摘いただけると嬉しいです。