More OOP-like version of Hangman
from random import choice | |
class board: | |
_HANGMAN = ( | |
""" | |
------ | |
| | | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
---------- | |
""", | |
""" | |
------ | |
| | | |
| O | |
| | |
| | |
| | |
| | |
| | |
| | |
---------- | |
""", | |
""" | |
------ | |
| | | |
| O | |
| -+- | |
| | |
| | |
| | |
| | |
| | |
---------- | |
""", | |
""" | |
------ | |
| | | |
| O | |
| /-+- | |
| | |
| | |
| | |
| | |
| | |
---------- | |
""", | |
""" | |
------ | |
| | | |
| O | |
| /-+-/ | |
| | |
| | |
| | |
| | |
| | |
---------- | |
""", | |
""" | |
------ | |
| | | |
| O | |
| /-+-/ | |
| | | |
| | |
| | |
| | |
| | |
---------- | |
""", | |
""" | |
------ | |
| | | |
| O | |
| /-+-/ | |
| | | |
| | | |
| | | |
| | | |
| | |
---------- | |
""", | |
""" | |
------ | |
| | | |
| O | |
| /-+-/ | |
| | | |
| | | |
| | | | |
| | | | |
| | |
---------- | |
""") | |
def __init__(self, *words): | |
self._used = [] | |
self._wrong_answers = 0 | |
self._words = [word for word in words] | |
self._word = choice(self._words) | |
self._so_far = "".join(["-" if c.isalpha() else " " for c in self._word]) | |
# This method is **NOT** part of OOP | |
# because it doesn't deal with logic. | |
def add_to_used_letters(self, guess): | |
self._used.append(guess) | |
# This method is OOP | |
# because it deals with logic | |
def check_answer(self, guess): | |
""" | |
Checks to see if the user's guess is correct. | |
:param guess: User's guess | |
""" | |
if guess in self._word: | |
position = self._word.find(guess, 0) | |
while position >= 0: | |
self._so_far = self._so_far[:position] + guess + self._so_far[position+1:] | |
position = self._word.find(guess, position + 1) | |
return True | |
# If the guessed letter is not in the word: | |
self._wrong_answers += 1 | |
return False | |
# OOP method | |
# because it deals with logic | |
def exists_in_used_letters(self, guess): | |
return guess in self._used # Does the guessed letter exist in used letters? | |
# OOP method | |
# because it deals with logic | |
def in_progress(self): | |
if self._wrong_answers == len(self._HANGMAN) or self._so_far == self._word: | |
return False | |
return True | |
# OOP method | |
# because it deals with logic | |
def game_won(self): | |
if self._wrong_answers == len(self._HANGMAN): | |
return False | |
return True | |
# This method is **NOT** part of OOP | |
# because it doesn't deal with logic. | |
def print_current_progress(self): | |
""" | |
Prints the current progress of the game. | |
""" | |
print() | |
print(self._HANGMAN[self._wrong_answers]) | |
print("Word so far: ", self._so_far) | |
print("Letters used: ", sorted(self._used)) |
# Whenever possible, only import specific functions from the library | |
from random import choice | |
from time import sleep | |
from board import board | |
class Hangman: | |
""" | |
A Hangman class. | |
""" | |
_POSITIVE_SAYINGS = ("Well done!", "Awesome!", "You Legend!") | |
def __init__(self): | |
""" | |
The Python constructor for this class. | |
""" | |
self._board = board("APPLE", "ORACLE", "MIMO", "TESLA") | |
def play(self): | |
""" | |
This is the main driver of the game. | |
Plays the game. | |
""" | |
self._reset_game() | |
self._start_game() | |
# The amount of incorrect answers should be no greater than the length | |
# of HANGMAN. | |
# | |
# Use the length of HANGMAN to ensure there's no index | |
# overflow error when printing result. | |
while self._board.in_progress(): | |
self._print_current_progress() | |
guess = self._user_guess() | |
self._check_result(guess) | |
self._wait() | |
self._print_result() | |
self._play_again() | |
# --------------------------------- | |
# "Private" methods | |
def _check_result(self, guess): | |
""" | |
Checks to see if the user's guess is correct. | |
:param guess: User's guess | |
""" | |
if self._board.check_answer(guess): | |
print(choice(self._POSITIVE_SAYINGS), "...Updating word so far...") | |
else: | |
print("INCORRECT! Try again!") | |
def _play_again(self): | |
""" | |
Asks the user if he or she would like to play again. | |
If the user wants to play again, calls play(). | |
Otherwise, thanks the user for playing. | |
""" | |
print("Would you like to play again?") | |
if input("Enter Y for yes or N for no: ").upper() == "Y": | |
self.play() | |
else: | |
print() | |
print("Thank you for playing!") | |
def _print_current_progress(self): | |
""" | |
Prints the current progress of the game. | |
""" | |
self._board.print_current_progress() | |
def _print_result(self): | |
""" | |
Prints the result (win or lose). | |
""" | |
self._wait() | |
print("Calculating result...") | |
self._wait() | |
if self._board.game_won(): | |
print("WINNER! Congratulations!") | |
else: | |
print("UNLUCKY! Better luck next time!") | |
def _reset_game(self): | |
""" | |
Resets the game by calling the constructor. | |
""" | |
self.__init__() | |
def _start_game(self): | |
""" | |
Starts the game by printing an introduction | |
and asks the user to hit the ENTER key to continue. | |
""" | |
print() | |
print("\t\tWelcome to Hangman!") | |
print() | |
input("Press Enter to START:") | |
def _user_guess(self): | |
""" | |
Asks for the user to guess a letter. | |
:returns: User's guessed letter. | |
""" | |
guess = input("Guess a letter: ").upper() | |
while self._board.exists_in_used_letters(guess): | |
self._wait() | |
print("Try again... You've already used this letter") | |
guess = input("Guess a letter: ").upper() | |
self._wait() | |
self._board.add_to_used_letters(guess) | |
return guess | |
def _wait(self): | |
sleep(1) # Time delay - allows user friendly reading | |
print() | |
if __name__ == '__main__': | |
game = Hangman() | |
game.play() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment