仕様
- ユーザーにじゃんけんの手を選んでもらう。(0:グー、1:チョキ、2:パー)
- プログラム側では、ユーザーと勝負するじゃんけんの手をランダムに選ぶ。
- 「ユーザーが選んだじゃんけんの手」と「プログラムがランダムに選んだじゃんけんの手」を表示する。
- ユーザーが勝った場合は「あなたの勝ちです。」と表示する。
- ユーザーが負けた場合は「あなたの負けです。」と表示する。
- あいこの場合は 「あいこで」と表示させたあともう一度じゃんけんをさせる。
- あいこが3回続いた場合は、「3回あいこが続きました。また挑戦してください。」と表示させたあとにプログラムを終了させる。
自分のコードとChatGPTのコードの比較
自分のコード
# 配列とあいこカウント用変数の定義
janken_hands = ["グー", "チョキ", "パー"]
aiko_count = 0
puts "最初はグー、じゃんけん..."
# 3回ループさせる
while aiko_count < 3
if aiko_count > 0
puts "あいこで"
end
puts "[0]:グー [1]:チョキ [2]:パー"
# ユーザの入力受取
usr_hand = gets.to_i
# 不正な入力の場合はメッセージを出力
while usr_hand < 0 || usr_hand > 2
puts "半角の「0」、「1」、「2」のいずれかを入力してください。"
usr_hand = gets.to_i
end
# プログラム側の手を生成
pgm_hand = rand(3)
puts "あなたの手:#{janken_hands[usr_hand]}, わたしの手:#{janken_hands[pgm_hand]}"
# 勝負がついたらそこで終了
if usr_hand - pgm_hand == -1 || usr_hand - pgm_hand == 2
puts "あなたの勝ちです。"
break
elsif usr_hand - pgm_hand == -2 || usr_hand - pgm_hand == 1
puts "あなたの負けです。"
break
else
aiko_count += 1
end
end
# あいこが3回続いた時のみ出力
if aiko_count == 3
puts "3回あいこが続きました。また挑戦してください。"
end
__END__
パターン分け
usrの勝ち
usr: 0 pgm: 1
usr: 1 pgm: 2
usr: 2 pgm: 0
pgmの勝ち
usr: 0 pgm: 2
usr: 1 pgm: 0
usr: 2 pgm: 1
あいこ
usr: 0 pgm: 0
usr: 1 pgm: 1
usr: 2 pgm: 2
ポイントは以下の2点です。
- 仕様には含まれていないが、ユーザの入力が不正である場合はメッセージを表示して正しい入力をしてもらうように促す。
- ユーザの手(
usr_hand
)と対戦相手のプログラムの手(pgm_hand
)の差を勝敗の判定に利用する。
(__END__
以下のコメントをご参照ください)
ChatGPTのコード
以下は、要件を満たすRubyプログラムの例です。
def judge(user, program)
if user == program
"draw"
elsif (user == 0 && program == 1) || (user == 1 && program == 2) || (user == 2 && program == 0)
"user"
else
"program"
end
end
def print_result(user_hand, program_hand, result)
puts "ユーザーの手: #{convert_hand(user_hand)}, プログラムの手: #{convert_hand(program_hand)}"
case result
when "user"
puts "あなたの勝ちです。"
when "program"
puts "あなたの負けです。"
when "draw"
puts "あいこで"
end
end
def convert_hand(hand)
case hand
when 0
"グー"
when 1
"チョキ"
when 2
"パー"
end
end
def main
user_draw_count = 0
while user_draw_count < 3
puts "じゃんけんの手を選んでください(0:グー、1:チョキ、2:パー):"
user_hand = gets.chomp.to_i
unless [0, 1, 2].include?(user_hand)
puts "無効な入力です。再度入力してください。"
next
end
program_hand = rand(3)
result = judge(user_hand, program_hand)
print_result(user_hand, program_hand, result)
if result == "draw"
user_draw_count += 1
else
user_draw_count = 0
end
end
puts "3回あいこが続きました。また挑戦してください。"
end
main
このプログラムでは、judge
メソッドでじゃんけんの勝敗を判定し、print_result
メソッドで結果を出力しています。main
メソッドでは、ユーザーがじゃんけんを選択し、結果を表示します。また、あいこが3回続いた場合にはループを終了し、終了メッセージを表示します。
学び
- ChatGPTは機能ごとにメソッドを定義しています。これが「「オブジェクト指向」なのでしょうか?
このようなコードを書けるようになりたいものです。 - ChatGPTも不正な入力の判定をしています。
include?()
はドットインストールで学んだ気がします。せっかく学んだことを使いこなせていないのが残念... - やはり自分以外の何者か(AI含む)が書いたコードを読むのは勉強になります。(現職の新人研修の講師の先生もおっしゃっていました)
ChatGPTによるコードレビュー
このコードは、じゃんけんゲームの基本的な機能を実装しており、動作する点では問題ありませんが、いくつかの改善点があります。以下にレビューを行います。
-
コード内のコメントや変数名は理解しやすくて良いですが、コメントが冗長に感じられる場合があります。コメントがコードの意図を明確に伝えている場合は問題ありませんが、コメントが明らかな場合は省略することも検討できます。
-
不正な入力を検出するためのループがありますが、
gets.to_i
では改行文字が数値に変換されてしまうため、不適切な入力が無視されずに無限ループに陥る可能性があります。この問題を解決するためには、gets.chomp.to_i
のように.chomp
を使用して改行文字を削除する必要があります。 -
コードの条件式が少し複雑であり、理解しにくい部分があります。条件式を読みやすくするために、関数や変数を使用して条件を説明することができます。
-
あいこが発生した場合、カウンターがインクリメントされていますが、次のループで条件を満たさなくても、カウンターが増加することになります。これは、不必要なカウントが行われる可能性があります。あいこが発生した場合は、カウンターをリセットする必要があります。
-
usr_hand - pgm_hand
の計算は、条件を判定するために使用されていますが、可読性を向上させるために、結果を予め計算して変数に格納することを検討することができます。 -
コードの終了後、
__END__
マーカーの下にコメントがあります。このコメントは、コードの機能とは関係がないため、不要です。
これらのポイントを考慮して、コードを改善することができます。以下は、修正したコードの例です。
janken_hands = ["グー", "チョキ", "パー"]
aiko_count = 0
puts "最初はグー、じゃんけん..."
while aiko_count < 3
if aiko_count > 0
puts "あいこで"
end
puts "[0]:グー [1]:チョキ [2]:パー"
usr_hand = gets.chomp.to_i
# 不正な入力をチェックする
until (0..2).include?(usr_hand)
puts "半角の「0」、「1」、「2」のいずれかを入力してください。"
usr_hand = gets.chomp.to_i
end
pgm_hand = rand(3)
puts "あなたの手:#{janken_hands[usr_hand]}, わたしの手:#{janken_hands[pgm_hand]}"
result = usr_hand - pgm_hand
if result == 1 || result == -2
puts "あなたの勝ちです。"
break
elsif result == -1 || result == 2
puts "あなたの負けです。"
break
else
aiko_count += 1
end
end
if aiko_count == 3
puts "3回あいこが続きました。また挑戦してください。"
end
このようにすることで、コードがより読みやすくなり、理解しやすくなります。
疑義
この中で特に修正が必要な点は、プログラムが正常に動作しない恐れのある「2」と「4」かと思う。
しかし、「4」で「(前略)カウンターをリセットする必要があります。」と書いてあるが、修正後のコードでカウンターをリセットしている箇所が見当たらない...
ChatGPTへの質問
「カウンターをリセットする必要があります。」とのことですが、それは修正後のコードのどの箇所のことですか?
ChatGPTの回答
申し訳ありません、その部分は修正後のコードには含まれていませんでした。元のコードでは、あいこの場合にカウンターが増加しますが、あいこが解消された後にそのカウンターがリセットされるべきです。つまり、aiko_count
が再び0に戻る必要があります。
修正後のコードでは、aiko_count
が再び0に戻る処理が不足していました。修正後のコードに以下のような行を追加することで、この問題を解決できます。
else
aiko_count = 0 # あいこが解消された場合、カウンターをリセットする
これにより、あいこのカウントが解消された場合に、aiko_count
がリセットされるようになります。
ChatGPTの模範解答を確認
申し訳ございませんが、以前の修正を行ったコードに、さらにリセット処理を追加したものが以下です。
janken_hands = ["グー", "チョキ", "パー"]
aiko_count = 0
puts "最初はグー、じゃんけん..."
while aiko_count < 3
if aiko_count > 0
puts "あいこで"
end
puts "[0]:グー [1]:チョキ [2]:パー"
usr_hand = gets.chomp.to_i
# 不正な入力をチェックする
until (0..2).include?(usr_hand)
puts "半角の「0」、「1」、「2」のいずれかを入力してください。"
usr_hand = gets.chomp.to_i
end
pgm_hand = rand(3)
puts "あなたの手:#{janken_hands[usr_hand]}, わたしの手:#{janken_hands[pgm_hand]}"
result = usr_hand - pgm_hand
if result == 1 || result == -2
puts "あなたの勝ちです。"
break
elsif result == -1 || result == 2
puts "あなたの負けです。"
break
else
aiko_count += 1
aiko_count = 0 if aiko_count == 3 # あいこが解消された場合、カウンターをリセットする
end
end
if aiko_count == 3
puts "3回あいこが続きました。また挑戦してください。"
end
この修正により、あいこのカウントが解消された場合に、aiko_count
がリセットされるようになります。
ん???
あいこが解消?したらカウンターをリセット?
分からなくなってしまったので、一旦ここで切ります。