Yohey's Slow Living

Take a break, have a cup of coffee, and have a nice day.

Python Practice Project #7: Fizz Buzz Bazz Game

#7の課題は、FizzBuzzGame。
最初に提示された課題は以下の通り。
課題内容
────────
1から100までの数字を順に出力します。
• 3の倍数のときは “Fizz
• 5の倍数のときは “Buzz”
• 3と5両方の倍数のときは “FizzBuzz
• それ以外のときは数字をそのまま表示

✨ 拡張ルール
• 7の倍数のときは “Bazz” を追加
• 3と7の倍数 → “FizzBazz”
• 5と7の倍数 → “BuzzBazz”
• 3, 5, 7全ての倍数 → “FizzBuzzBazz”

💡 ヒント
• forループを使う
• if文を使う
• %演算子を使って割り切れるか判定する
────────

上記の課題を基に最初にかいていたコード
────────
#Day 7 FizzBuzz Game

number_list = range(1, 100)
output_number = 1

def user_guess():
print("\nGuess your answer from the list below. Press Q to quit.")
print("1:Fizz 2:Buzz 3:Bazz\n4:FizzBuzz 5:FizzBazz 6:BuzzBazz 7:FizzBuzzBazz")
user_input = input("Enter: ").lower()
if user_input == "q":
return


def calculation():
for stage in range(1, 101):
if stage % 3 != 0 and stage % 5 != 0 and stage % 7 != 0:
print(f"{stage} is not fizz/buzz/bazz number so skip to next number.")
else:
user_guess()
print("----------")
if stage % 3 == 0 and stage % 5 == 0:
print(f"The number is {stage} which is FizzBuzz!\n")
elif stage % 3 == 0:
print(f"The number is {stage} which is Fizz!\n")
elif stage % 5 == 0:
print(f"The number is {stage} which is Buzz!\n")
elif stage % 7 == 0:
print(f"The number is {stage} which is Bazz!\n")
else:
print(f"The number is {stage}.\n")

def calculation_result():
player_score = 0
if user_guess() == 1:
player_score += 1
print(f"{player_score}")

if __name__ == "__main__":
calculation()


────────

ChatGPTから指摘された改善点

問題点と改善点
1. number_list = range(1, 100) の範囲が誤っている
• range(1, 100) だと 1 から 99 まで しか含まれません。
• range(1, 101) に変更することで、100 まで含まれるようにしましょう。
2. user_guess() 関数の return が機能していない
• user_guess() の return が None のままで、ユーザーの入力を返していない ため、後で使えません。
• return user_input とすることで、ユーザーの回答を関数の外で使えるようにする。
3. calculation() 関数の出力フォーマットの整理
• 既存の print() のロジックは冗長になっているため、条件分岐を整理するとスッキリします。
4. calculation_result() 関数のロジックが機能していない
• if user_guess() == 1: の判定はおそらく "1"(文字列)と 1(整数)を誤って比較しています。
• user_guess() は str を返すため、比較する前に int() へ変換する必要があります。

ChatGPTから提案されたコード
# Day 7 FizzBuzz Game

import sys  # ゲームを途中終了するために使用

def user_guess():
    """ユーザーの回答を取得する"""
    print("\nGuess your answer from the list below. Press Q to quit.")
    print("1: Fizz  2: Buzz  3: Bazz\n4: FizzBuzz  5: FizzBazz  6: BuzzBazz  7: FizzBuzzBazz")
    user_input = input("Enter: ").lower()
    
    if user_input == "q":
        print("Game Over. Thanks for playing!")
        sys.exit()  # ゲームを途中終了
    
    return user_input  # ユーザーの入力を返す

def fizzbuzz_bazz(number):
    """FizzBuzzBazzの判定を行い、対応する文字列を返す"""
    result = ""
    
    if number % 3 == 0:
        result += "Fizz"
    if number % 5 == 0:
        result += "Buzz"
    if number % 7 == 0:
        result += "Bazz"
    
    return result if result else str(number)  # 何も該当しない場合は数字を返す

def calculation():
    """ゲームのメインループ"""
    player_score = 0

    for number in range(1, 101):
        correct_answer = fizzbuzz_bazz(number)  # 正解のFizzBuzzBazz値
        print(f"\nNumber: {number}")
        user_answer = user_guess()

        # ユーザーの回答が正しいかチェック
        expected_inputs = {
            "fizz": "Fizz", "buzz": "Buzz", "bazz": "Bazz",
            "fizzbuzz": "FizzBuzz", "fizzbazz": "FizzBazz",
            "buzzbazz": "BuzzBazz", "fizzbuzzbazz": "FizzBuzzBazz"
        }

        if user_answer in expected_inputs and expected_inputs[user_answer] == correct_answer:
            print("✅ Correct!")
            player_score += 1
        else:
            print(f"❌ Wrong! The correct answer was: {correct_answer}")

        print(f"Current Score: {player_score}\n" + "-" * 20)

    print(f"Game Over! Your final score: {player_score}")

if __name__ == "__main__":
    calculation()

────────

最終的に出来上がったコードがこちら
改善した点はつぎのものなど
・Noneという選択肢を加えた
・ゲームのステージを表示
・正答率を算出
・ステージ1でゲームをやめた場合は終了メッセージのみ表示し、ステージ2以降であればスコアと正答率を表示
────────

#Day 7 FizzBuzz Game
import sys

def fizzbuzz_bazz(number):
    """FizzBuzzBazzの判定"""
    result = ""
    if number % 3 == 0:
        result += "Fizz"
    if number % 5 == 0:
        result += "Buzz"
    if number % 7 == 0:
        result += "Bazz"
    if number % 3 != 0 and number % 5 != 0 and number % 7 != 0:
        result += "None"
    #上記以外の場合はNoneを選択肢に加え、それを選択すると正解にするようにする
    return result

def calculation():
    player_score = 0
    playing_stage = 1
    def user_guess_new():
        print("\nGuess your answer from the list below. Press Q to quit.")
        print("0:None 1:Fizz 2:Buzz 3:Bazz\n4:FizzBuzz 5:FizzBazz 6:BuzzBazz 7:FizzBuzzBazz")
        user_input = input("Enter: ").lower()
        if user_input == "q" and playing_stage == 1:
            print("Thank you for playing. Hope to see you soon!")
            sys.exit()
        elif user_input == "q":
            print(f"End Game. Your final score: {player_score}. Correct answer rate: {correct_answer_rate:.1f}%")
            print("Thank you for playing. Hope to see you again!")
            sys.exit()
        return user_input

    for number in range(1, 101):
        correct_answer = fizzbuzz_bazz(number)
        print(f"Stage#{playing_stage}. Q. Number: {number}")
        user_answer = user_guess_new()
        playing_stage += 1
        expected_inputs = {
            "fizz": "Fizz", "buzz": "Buzz", "bazz": "Bazz",
            "fizzbuzz": "FizzBuzz", "fizzbazz": "FizzBazz",
            "buzzbazz": "BuzzBazz", "fizzbuzzbazz": "FizzBuzzBazz", "none": "None"
        }
        if user_answer in expected_inputs and expected_inputs[user_answer] == correct_answer:
            print("Correct!")
            player_score += 1
            correct_answer_rate = (player_score / (playing_stage-1)) * 100
        else:
            print(f"Oops! The answer was {correct_answer}.")
            player_score += 0
            correct_answer_rate = (player_score / (playing_stage-1)) * 100
        print(f"Current Score: {player_score}. Correct answer rate: {correct_answer_rate:.1f}%") #これまでの正答率をX%で表示するようにしたらゲーム性がプラスされて面白いかも?
        print("----------")

    print(f"Game set! Your final score: {player_score}")


if __name__ == "__main__":
    calculation()


#3の倍数のときは “Fizz”
    # %で余り0を調べられる
#5の倍数のときは “Buzz”
    # 
#3と5両方の倍数のときは “FizzBuzz”

#それ以外のときは数字をそのまま表示

#--------------------------
#☑7の倍数のときは “Bazz” を追加
#3と7の倍数 → “FizzBazz”
#5と7の倍数 → “BuzzBazz”
#3, 5, 7全ての倍数 → “FizzBuzzBazz”
#my ideas-------------------
#☑earn points
#☑let the user to quit whenever they want
#my notes-------------------
#x回処理を繰り返すというのはfor文をつかう。書き方は,for VARIABLE in range(x, y):という書き方
||< 
────────

一番最初に書いたコードと、最終盤のコードではだいぶん改善されたと思う。
個人的にChatGPTを利用したコードの勉強で何が良いって、一番最初に提示したような中途半端な出来のコードでも問題点を指摘してくれ、
それを解決するにはどうしたらよいか?という道筋を示してくれるところ。
「じゃあこうすれば、この問題は解決されるのかな?」と考えるきっかけとなり、自分で考える力がつくような気がする。

また、前に進めるようになることで、次はどうしたいか?というアクションを考えるきっかけにもなる。
冒頭のとおり、最初の時点ではChatGPTから点数をカウントしたり、今プレイしているステージ#を表示したり、正答率を表示せよといった課題はなかった。
けれど、自分でコードを書いていくうちに、ゲームとして作るならこういう機能があったほうがいいのでは?といった考えが浮かび、
それを実装するにはどうしたらいいだろう?と考え、試行錯誤することができた。
こんな感じで、Pythonの勉強を続けていきたいと思った次第でした。

** 今回の学び
・順に出力する方法
Pythonでは for ループと range() 関数を使うと簡単に実現できる。
以下のような書き方をする。
>|python|
for i in range(1, 101):
    print(i)
||< 

・関数の中に関数を作ることができる(Nested Function / ローカル関数)
こんな感じ。
>|python|
def calculation():
    def user_guess():
        print("Guessing now...")
        return "fizz"

    user_answer = user_guess()
    print(f"User guessed: {user_answer}")

calculation()