質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

PyCharm

エディター・開発ツール

Q&A

解決済

3回答

3886閲覧

Python3で初めて作った数当てゲームの評価、添削をお願いします。

HIROKIdesuga

総合スコア7

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

PyCharm

エディター・開発ツール

0グッド

0クリップ

投稿2020/03/15 19:27

編集2020/03/16 15:42

前提・実現したいこと

Python3で初めて作った数当てゲームの評価、添削をお願いします。

発生している問題

気をつけた方がいい箇所が自力では見つけきれないので、出来るだけ頑張って書きました、添削をできればお願いします。

該当のソースコード

python

1import random 2# import os 3 4VAL_MIN = 1 5VAL_MAX = 100 6 7 8def ask_number(): 9 while True: 10 n = 0 11 s = input("回答:") 12 if s.isdigit(): 13 n = int(s) 14 if VAL_MIN <= n <= VAL_MAX: 15 return n 16 17 print("{}以上{}以下の整数を入力してください\n".format(VAL_MIN, VAL_MAX)) 18 19 20def ask_yes_no(): 21 print("もう一度遊びますか?y/n") 22 while True: 23 ans = input() 24 if ans in ('y', 'n'): 25 return ans 26 27 print("※y(yes)かn(no)を入力してください!\n") 28 29 30def play(): 31 print("{}~{}のランダムな整数を生成しました、正しい数字を当ててください。\n".format(VAL_MIN, VAL_MAX)) 32 num = random.randint(VAL_MIN, VAL_MAX) 33 try_count = 0 34 35 while True: 36 n = ask_number() 37 try_count += 1 38 39 if n == num: 40 print("おめでとうございます、正解です!") 41 print("チャレンジ回数{}、次もがんばってください。".format(try_count)) 42 return 43 44 if n > num: 45 print("答えより大きいです、もう一度当ててみましょう!\n") 46 else: 47 print("答えより小さいです、もう一度当ててみましょう!\n") 48 49 50def clear_screen(): 51 print("\033[2J") # for ANSI terminal 52 # # os.system('cls') # for windows 53 54 55def game(): 56 while True: 57 play() 58 if ask_yes_no() == 'n': 59 print("遊んでいただいてありがとうございました、またのご利用お待ちしております!") 60 return 61 clear_screen() 62 63 64game()

試したこと

while文の使い方の工夫(continueやbreak)、全体のループ

補足情報(FW/ツールのバージョンなど)

バージョン:Python3.7.7
エディタ:PyCharm CE

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hoshi-takanori

2020/03/15 19:58

無効な数(100 より大きかったりマイナスだったり)を入れても「0以上100以下の数字を入力してください」が出ませんね。
HIROKIdesuga

2020/03/15 20:07

hoshi-takanoriさん、修正の依頼ありがとうございます!更新します!
hoshi-takanori

2020/03/15 20:30

無限ループにならなかった。ざんねん…。添削します。
HIROKIdesuga

2020/03/15 20:32

危ういところでした、なんとか回避です!
guest

回答3

0

  • このコードは flake8 というツールでの書式チェックは警告が 0 です。

  • 機能毎に関数分割してます。

  • 画面クリアは 改行 100 回出力とは異なる方法で書いてみました。
    (windows と linux 系では異なる処理になってしまってますが)

  • その他 いろいろ 小さな変更をしています。
    (最小値が 0 なのか 1 なのか のバグ? も修正しています。

wc.py

python3

1import random 2# import os 3 4VAL_MIN = 1 5VAL_MAX = 100 6 7 8def ask_number(): 9 s = input("回答:") 10 while True: 11 if s.isdigit(): 12 n = int(s) 13 if VAL_MIN <= n <= VAL_MAX: 14 return n 15 16 print("{}以上{}以下の整数を入力してください\n".format(VAL_MIN, VAL_MAX)) 17 18 19def ask_yes_no(): 20 print("もう一度遊びますか?y/n") 21 while True: 22 ans = input() 23 if ans in ('y', 'n'): 24 return ans 25 26 print("※y(yes)かn(no)を入力してください!\n") 27 28 29def play(): 30 print("{}~{}のランダムな整数を生成しました、正しい数字を当ててください。\n".format(VAL_MIN, VAL_MAX)) 31 num = random.randint(VAL_MIN, VAL_MAX) 32 try_count = 0 33 34 while True: 35 n = ask_number() 36 try_count += 1 37 38 if n == num: 39 print("おめでとうございます、正解です!") 40 print("チャレンジ回数{}、次もがんばってください。".format(try_count)) 41 return 42 43 if n > num: 44 print("答えより大きいです、もう一度当ててみましょう!\n") 45 else: 46 print("答えより小さいです、もう一度当ててみましょう!\n") 47 48 49def clear_screen(): 50 print("\033[2J") # for ANSI terminal 51 # # os.system('cls') # for windows 52 53 54def game(): 55 while True: 56 play() 57 if ask_yes_no() == 'n': 58 print("遊んでいただいてありがとうございました、またのご利用お待ちしております!") 59 return 60 clear_screen() 61 62 63game()

追記
ask_number はバグがありました。
(数字以外や 範囲外の値を入力したときの挙動)
次のようにしたほうが良さそうです。

python3

1def ask_number(): 2 s = input("回答:") 3 while True: 4 if s.isdigit(): 5 n = int(s) 6 if VAL_MIN <= n <= VAL_MAX: 7 return n 8 print("{}以上{}以下の整数を入力してください\n".format(VAL_MIN, VAL_MAX)) 9 s = input()

投稿2020/03/16 13:27

編集2020/03/18 14:21
katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

HIROKIdesuga

2020/03/16 15:34 編集

katoyさんコメントありがとうございます! flake8を実際入れてみて使ってみました、とても便利です! wc.pyをプレイしてみましたが、入力部分で何を入れても先に進まなかったので、自分で直してみました。 ソースコードを更新しますので、よろしかったら添削お願いいたします。
HIROKIdesuga

2020/03/16 15:38

正確には文字列や範囲外の数字を入れた場合先に進まなかったので、 関数ask_numberの部分を自分なりに直してみました、よろしかったら添削お願いします。
katoy

2020/03/17 13:15

ask_number はバグってましたね。 回答に少し訂正した ask_number をかきました。(テストはしていません) 本来は メソッド毎に テストコードを書くべきです。 python での テストコードの書き方も研究してみてください。 (Ctrl-C や Ctrl-D, ctrl-Z などを入れたときにどんな挙動をさせたいかも考慮するとよいです)
HIROKIdesuga

2020/03/17 20:43

テストコードですね、重要と聞くのでしっかり書いていきます。 katoyさん、添削評価ありがとうございました!
guest

0

ネストとcontinueの多用が気になったので、関数単位で分けてみました。
1-100の整数を受け取るまでのif文と数の判定のif文が並んでいた部分も、可読性のために入力受け取りを分けました。

Python

1from random import randint 2 3 4def guess_number() -> None: 5 num = randint(1, 100) 6 count = 0 7 print("1~100のランダムな整数を生成しました、正しい数字を当ててください。\n") 8 while True: 9 user_input = get_user_input() 10 count += 1 11 if user_input == num: 12 print("おめでとうございます、正解です!") 13 break 14 elif user_input > num: 15 print("答えより大きいです、もう一度当ててみましょう!\n") 16 else: 17 print("答えより小さいです、もう一度当ててみましょう!\n") 18 19 print(f"チャレンジ回数{count}、次もがんばってください。\n") 20 21 22def get_user_input() -> int: 23 raw_input = input("回答: ") 24 if raw_input.isdigit() and 1 <= (int_input := int(raw_input)) <= 100: 25 return int_input 26 print("1以上100以下の整数を入力してください\n") 27 return get_user_input() 28 29 30def main(): 31 while True: 32 guess_number() 33 34 while (b := input("もう一度遊びますか?y/n ")) not in "yn": 35 continue 36 if b == "y": 37 print("-" * 10) 38 else: 39 break 40 41 print("遊んでいただいてありがとうございました、またのご利用お待ちしております!") 42 43 44if __name__ == "__main__": 45 main()

投稿2020/03/15 22:19

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

HIROKIdesuga

2020/03/16 06:22

solzardさん、添削ありがとうございます! この場合の、機能を関数別に分ける方法をよく理解できました! その中でひとつ疑問があるのですが、関数get_user_input()でreturn int_inputのint_inputが Local variable 'int_input' might be referenced before assignment というエラーを表示させています。 これは変数bと何が違って、どういう対処をしたらいいですか? 一応関数get_user_input()の最初にint_input=""と付け加えたら消えたのですが、それで大丈夫でしょうか?
退会済みユーザー

退会済みユーザー

2020/03/16 08:49 編集

int_input := int(raw_input)としてif文中でセイウチ演算子を使って定義し、その評価が真のときのみreturn int_inputと使われるので実は問題は起きません。 もし気になるようでしたら、 if raw_input.isdigit() and 1 <= (int_input := int(raw_input)) <= 100: return int_input の部分を、従来のように if raw_input.isdigit() and 1 <= int(raw_input) <= 100: return int(raw_input) と書き換えてくださっても構いません。 := のセイウチ演算子は昨秋のPython3.8で追加された新機能なので、PyCharmではまだ対応できていないようです。 今回のように、直前に宣言しているなどで問題ないと自信があるときは、私は"might be referenced before assignment"のエラーは無視しています。 Intellijのバグリポートに報告はされているので、将来的には文脈に応じて判断されるようになるでしょう。 セイウチ演算子についてあまりご存じないようでしたら、下記の記事が分かりやすいかと思います。 https://atsuoishimoto.hatenablog.com/entry/2019/09/03/110508
HIROKIdesuga

2020/03/16 09:02 編集

solzardさん、詳細な解説ありがとうございます! セイウチ演算子についても、初めて聞きました。 まだまだ自分の勉強不足な部分が多いので、インプットの量を増やしてかつアウトプットもいいバランスで行えたらなと考えています。 solzardさん、大変勉強になりました、ありがとうございます。
guest

0

ベストアンサー

python はあまり詳しくないので、一般的なプログラミングの観点から添削します。

python

1import random 2 3flag = "y" 4while flag == "y":

flag はループ中で代入してないので、ずっと "y" のままですね。そういう場合は単純に while True: としましょう。
参考: Pythonのwhile文によるループ処理(無限ループなど) | note.nkmk.me

python

1 num = random.randint(1,100) 2 count = 0 3 a = 0 4 print("1~100のランダムな数字を生成しました、正しい数字を当ててください。\n") 5 while a != num: 6 a = input("回答:") 7 a = int(a) 8 while (a > 100) | (a < 0): 9 print("0以上100以下の数字を入力してください\n") 10 a = input("回答:") 11 a = int(a) 12 continue

この部分、元は

python

1 while a > 100 | a < 0: 2 print("0以上100以下の数字を入力してください\n") 3 continue

となっていて、| がビット和のために絶対に成り立たない条件になってましたが、or を使っていれば無効な数(マイナスまたは 101 以上)の場合には無限に「0以上100以下の数字を入力してください」が出力されるはずでした。ここは while ではなく if を使って単純に

python

1 if a > 100 or a < 0: 2 print("0以上100以下の数字を入力してください\n") 3 continue

とすれば良かったと思います。なお、ビット和については後で書きます。

python

1 if a > num: 2 print("答えより大きいです、もう一度当ててみましょう!\n") 3 elif a == num: 4 print("おめでとうございます、正解です") 5 break 6 else: 7 print("答えより小さいです、もう一度当ててみましょう!\n")

「大きい」「正解」「小さい」という判定の順序が気になります。先に正解を判定して、後から「大きい」「小さい」を判定する方が分かりやすいと思います。

python

1 count += 1 2 print("チャレンジ回数{}、次はもっとがんばりましょう".format(count))

もしも 1 回で正解すると、「チャレンジ回数0」と表示されますが、それでいいのかな?

python

1 print("もう一度遊びますか?y/n") 2 b = 0

未入力を表す b の初期値ですが、0 よりも None または "" がいいと思います。

python

1 while (b != "y") & (b != "n"):

論理積(かつ)や論理和(または)は and や or を使いましょう。
参考: Pythonの論理演算子and, or, not(論理積、論理和、否定) | note.nkmk.me

|& はビット和やビット積と言って、論理値(True や Flase)ではなく 2 進数の計算になります。また、演算子の優先順位も違うので括弧が必要になったりしますね。
参考: Python ビット演算 超入門 - Qiita

python

1 b = input() 2 print("y(yes)かn(no)を入力してください\n") 3 continue 4 if b == "n": 5 break 6 7print("遊んでいただいてありがとうございました、またのご利用お待ちしております!")

全体的には読みやすくて綺麗なコードだと思います。がんばってください。

投稿2020/03/15 20:36

編集2020/03/15 20:55
hoshi-takanori

総合スコア7901

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

HIROKIdesuga

2020/03/15 21:22

たくさんの添削ありがとうございます! while文やif文の使い分けなど、いろんな点において気をつけることを知ることができました。 添削していただいた問題点に加え、入力値の判別もより厳密に修正しました。 よろしかったら最終チェックしていただけるとありがたいです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問