Skip to content

Instantly share code, notes, and snippets.

@devwolf75
Last active October 3, 2018 22:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save devwolf75/6cffc1d3b2acd8d2fd06d3c22aaa8f98 to your computer and use it in GitHub Desktop.
Save devwolf75/6cffc1d3b2acd8d2fd06d3c22aaa8f98 to your computer and use it in GitHub Desktop.
Play an implementation of a guessing game against the PC.

Written to serve as an example to the following Reddit post on the /r/learnpython: Rate my code! Beginner trying to improve

The code is to serve as an idea and example on how to further improve the code for the game in order to make it more modular and extensible.

Tasks

  • Add tests with pytest.
  • Split the file into different files with classes and methods.
import logging
import random
ENTER_HIGHEST_VALUE = "What would you like the highest value to be?"
NUMBER_NOT_VALID = "That is not a number. :("
NUMBER_NOT_IN_RANGE = "I don't know how to play with negative numbers. Sorry... :("
NUMBER_CANNOT_BE_HIGHER_THAN = "Sorry, but the guess cannot be higher than the highest number:"
ENTER_GUESS = "Guess the number. :)"
TRY_AGAIN = "Try again."
HIGHER = "My number is higher!"
LOWER = "My number is lower!"
YOU_WIN = "That is my number! You win!"
PLAY_AGAIN = "Would you like to play again?"
DID_NOT_UNDERSTAND = "I did not understand. :("
GOODBYE = "Thanks for playing."
def play():
game_active = True
game = new_game()
# Main game loop.
while game_active:
# Ask for guess.
while not game.is_over():
guess = get_validated_number_input(ENTER_GUESS, game.get_upper_bound())
# Main game logic.
if not game.check_answer(guess):
if game.rate_guess_approxiamtion(guess) == 0:
logger.log_message("{} {}".format(HIGHER, TRY_AGAIN))
else:
logger.log_message("{} {}".format(LOWER, TRY_AGAIN))
else:
logger.log_message(YOU_WIN)
# Ask if player wants to play again
remake = input("{}\n".format(PLAY_AGAIN))
if remake.lower() in ["y", "yes", "t", "true"]:
game = new_game()
else:
logger.log_message(GOODBYE)
game_active = False
def new_game():
"""Creates a new GuessingGame instance with the initialization."""
highest_value = get_validated_number_input(ENTER_HIGHEST_VALUE)
return GuessingGame(highest_value)
def get_validated_number_input(get_value_message: str = "Enter a number.", max_value: int = None):
"""Prompts the user input with a message and checks that the value is valid number.
If needed it can validate if the number is within a range.
:param get_value_message: Message to display when prompting for input.
:param max_value: An optional max value that may limit the user input.
:return: The validated number as integer.
"""
while True:
try:
value = int(input("{}\n".format(get_value_message)))
except ValueError:
logger.log_message("{}\n".format(NUMBER_NOT_VALID))
continue
if value >= 0:
if max_value and max_value < value:
logger.log_message("{} {}".format(NUMBER_CANNOT_BE_HIGHER_THAN, max_value))
continue
break
else:
logger.log_message("{}\n".format(NUMBER_NOT_IN_RANGE))
return value
class Logger:
def __init__(self):
logging.basicConfig(level=logging.INFO, format="")
self.logger = logging.getLogger(__name__)
def log_message(self, message: str):
"""Logs a message into the screen.
:param message: The message to display.
"""
self.logger.info("{}\n".format(message))
class GuessingGame:
def __init__(self, upper_bound: int):
self.upper_bound = upper_bound
self.cpu_number = random.randint(1, int(upper_bound))
self.game_over = False
def get_upper_bound(self):
"""Returns the instance upper bound."""
return self.upper_bound
def get_cpu_number(self):
"""Returns the guess number."""
return self.cpu_number
def check_answer(self, guess: int) -> bool:
"""Checks if a given guess is correct.
:param guess: The guessed number to check against the computer.
:return: A boolean that states if the answer is correct or not.
"""
if self.cpu_number == guess:
self.game_over = True
return True
return False
def rate_guess_approxiamtion(self, guess: int) -> int:
"""Given a wrong guess, it rates the approximation.
:param guess: The guessed number to check against the computer.
:return: An integer of 1 if the guess is greater than the computer number,
0 if it is lower.
"""
return 1 if guess > self.cpu_number else 0
def is_over(self):
"""Tells wether the game is over.
:return: The game status.
"""
return self.game_over == True
if __name__ == "__main__":
logger = Logger()
play()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment