3
\$\begingroup\$

I'm learning Python and I'm building a basic random numbr generator. The code below works as expected. I'm just wondering if it uses best practice / can be made better.

Some future considerations might be adding a way for users to pick a random that isn't limited to 0-50 or 0-100, and finding a way to scale the number of guesses dynamically based on their choice.

import random

"""
Make a program in which the computer randomly chooses a number between 1 to 10,
1 to 100, or any range.
"""


def intro():
    print(f"Welcome to our number guessing game.")
    print(f"We'll ask you to pick a range of numbers from 0 up to 100."
          f"Then you'll get some chances to guess the number. "
          f"The number of guesses you get will scale based on the range you "
          f"choose. From 0 - 50, you'll get 5 chances. From 0 - 100, you'll"
          f"get 10 chances. Good luck!")
    print("Choose a range: ")
    print("1. 0 - 50")
    print("2. 0 - 100\n")
    num_guesses = {
        "1": (5, 50),
        "2": (10, 100)
    }
    num_range = input()
    while True:
        if num_range == "1" or num_range == "2":
            return num_guesses[num_range]
        else:
            print(f"{num_range} is not a valid selection. "
                  f"Please select either 1 or 2.")
            num_range = input()


def guess_number(num_guesses, num_range):
    random_number = random.randint(0, num_range)
    guess_count = 0
    print(f"Random num is: {random_number}")
    while guess_count < num_guesses:
        guess = int(input(f"Pick a random number between 0 and "
                          f"{num_range}: \n"))
        if guess == random_number:
            print("CONGRATS, YOU WIN!")
            break
        else:
            guess_count += 1
            print(f"Incorrect, try again! You have "
                  f"{num_guesses - guess_count} guess(es) left.\n")
    else:
        print("Womp womp, you lose :(.")


if __name__ == "__main__":
    num_guesses, num_range = intro()
    guess_number(num_guesses, num_range)
\$\endgroup\$
1
  • \$\begingroup\$ In guess_number(), print(f"Random num is: {random_number}") comes before the while loop. Doesn't that tell the user what the number is before they make any guesses? It should probably go at the end with print("Womp womp, you lose :(."). \$\endgroup\$ – RootTwo Feb 12 at 23:10
3
\$\begingroup\$

First, an issue with behaviour: In guess_number you don't make sure the input from the user is a number at all. So you might end up calling int("oops"). This raises a ValueError, and since there's nothing to catch that, the program crashes. You'll want to do something about that. A simple solution could be

try:
    guess = int(input(...))
    if guess == random_number:
        ...
    else
        ...
except ValueError:
    print("That doesn't look like a number to me, but that's OK, I'll count it anyway :)")
    guess_count += 1

Side note, guesses that aren't in the interval also add to the counter. That might be on purpose, but since the validity of the input wasn't checked at all I don't want to assume, so I'm pointing it out.

There are also a couple minor issues with intro

First off, you're duplicating the num_range = input() line. If you get the input at the start of the loop (before the if) instead it'll be easier to change if for some reason you need to

Second, in python the usual approach is that it's better to ask for forgiveness than permission. That if check would usually be written using a try/except KeyError block (a bit like above). But if you don't want to do that, a more robust approach than the current one could be to check if num_range in num_guesses, in case a new option is added, or the program changes from accepting 1 and 2 to accepting "a" and "b".

On a related third note, the messages don't actually know what options are available, so there's a risk they get out of sync with the rest of the program. You can get a list of valid options as num_guesses.keys(), or use a for loop to iterate over the keys in num_guesses directly

Finally, I don't love the variable names. num_guesses sounds like it should be the number of guesses, but it isn't a number at all. Similarly, num_range doesn't have much to do with ranges of numbers either. num_range feels like it would be better described by a name like selection or choice, and num_guesses is a collection of available options, so maybe it could be called options?

options = {
    "1": (5, 50),
    "2": (10, 100)
}

print("Welcome to ... on the range you choose.")

for option in options:
    print(f"From 0 - {options[option][1]}, you'll get {options[option][0]} chances.")

while True:
    print("Choose a range:")
    for option in options:
        print(f"{option}. 0 - {options[option][1]}")

    selection = input()
    try:
        return options[selection]
    except KeyError:
        print(f"{selection} is not a valid selection.")
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.