|
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() |