Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from random import choice
- from bs4 import BeautifulSoup
- from string import ascii_letters
- import requests, sys, webbrowser
- class Hangman:
- def __init__(self, *words):
- """A text-based game of the all-time classic, Hangman. Can you save the man from the gallows?
- :param words:
- Word(s) to be used for the game. String(s) can be passed directly as parameter(s) or in a list or
- in a tuple. A word is chosen by random and assigned to 'self.word', which is then used for the
- player to guess in a game of a hangman.
- """
- while isinstance(words, list) or isinstance(words, tuple):
- words = choice(words)
- if not isinstance(words, str):
- raise TypeError(f"Expected 'str' type. Got {type(words)} instead.")
- self.word = words.lower()
- self.guesses = set(' ')
- self.attempts = 8
- self.center = num if (calc := len(self.word) * 2 - 1) < (num := 15 + len(self.word)) else calc
- def play(self):
- """Initiate a game of hangman.
- """
- self.draw_hangman()
- while not set(self.word).issubset(self.guesses):
- if (guess := self.get_letter()) in set(self.word):
- self.success_msg(guess)
- continue
- if self.failed_msg(guess):
- return
- print(f"{'YOU WIN':^{self.center}}\n{'You guessed ' + self.word.upper():^{self.center}}\n")
- def get_letter(self):
- """Return a single letter from the player's input. Also checks if the input is unique from previous inputs.
- """
- while True:
- if (guess := input('Enter a letter: ').lower()).startswith('/'):
- self.commands(guess[1:])
- return ' '
- if len(guess) > 1 or not guess.isalpha():
- print("Please enter one letter.")
- continue
- if guess in self.guesses:
- print(f"You already entered '{guess}'. Please enter another letter.")
- continue
- return guess
- def commands(self, command):
- """User commands that can alter the games state.
- :reset: Resets attempts to default value(8).
- :inc : Increment attempts by 1.
- :dec : Decrement attempts by 1.
- :free : Allows the player to enter any amount letters without decrementing attempts.
- :show : Reveals the answer.
- :solve: Automatically win the game.
- :quit : Quit the game.
- """
- cmds = {
- 'reset': lambda: (setattr(self, 'attempts', 8), print(f"Attempts reset back to {self.attempts}.")),
- 'inc' : lambda: (setattr(self, 'attempts', self.attempts + 1), print('Attempts incremented by 1.')),
- 'dec' : lambda: (setattr(self, 'attempts', self.attempts - 1), print('Attempts decremented by 1.')),
- 'free' : lambda: self.guesses.update(input('Enter any letter(s): ')),
- 'show' : lambda: print(self.word),
- 'solve': lambda: self.guesses.update(self.word),
- 'quit' : lambda: sys.exit(0)
- }
- try:
- cmds[command]()
- except KeyError:
- print('Unknown command.')
- def success_msg(self, guess):
- """Display a success message along with the current progress of the game. Also updates set for correct guesses.
- """
- self.guesses.update(guess)
- print(f"\n{'SUCCESS!':^{self.center}}")
- self.draw_hangman()
- def failed_msg(self, guess):
- """Display a failed message along with the current progress of the game. Also updates set for incorrect guesses
- and subtracts one from attempts
- :returns:
- Returns True if the player still has attempts. Otherwise, returns False.
- """
- self.attempts -= 1
- self.guesses.update(guess)
- print(f"\n{'FAILED!':^{self.center}}")
- self.draw_hangman()
- if self.attempts < 1:
- print(f"{'GAME OVER':^{self.center}}\n{'The answer was ' + self.word.upper():^{self.center}}\n")
- self.attempts = 8
- return True
- return False
- def draw_hangman(self):
- """Displays the number of attempts remaining and draws the hangman based on the attempts the player has left.
- Also shows the player's progress on what letters they've guessed correctly.
- """
- print(f"{str(self.attempts) + ' Attempts left':^{self.center}}")
- # Displays hangman board when these strings are joined with a new line separator. i.e. '\n'.join(_hangman)
- _hangman = [' _____ ', ' | | ', ' | ', ' | ', ' | ', ' _|_']
- # Modifies the hangman board based on player attempts.
- if self.attempts < 8: _hangman[2] = f"{_hangman[2][:2]}O{_hangman[2][3:]}" # Draw head
- if self.attempts < 7: _hangman[3] = f"{_hangman[3][:1]}/{_hangman[3][2:]}" # Draw left arm
- if self.attempts < 6: _hangman[3] = f"{_hangman[3][:2]}|{_hangman[3][3:]}" # Draw torso
- if self.attempts < 5: _hangman[3] = f"{_hangman[3][:3]}\\{_hangman[3][4:]}" # Draw right arm
- if self.attempts < 4: _hangman[4] = f"{_hangman[4][:0]}_{_hangman[4][1:]}" # Draw left foot
- if self.attempts < 3: _hangman[4] = f"{_hangman[4][:1]}/{_hangman[4][2:]}" # Draw left leg
- if self.attempts < 2: _hangman[4] = f"{_hangman[4][:2]}'\\{_hangman[4][4:]}" # Draw right leg
- if self.attempts < 1: _hangman[4] = f"{_hangman[4][:4]}_{_hangman[4][5:]}" # Draw right foot
- print(*[f"{section:^{self.center}}" for section in _hangman], sep='\n')
- print(f"{' '.join([x.upper() if x in self.guesses else '_' for x in self.word]):^{self.center}}", '\n')
- class Comment:
- def __init__(self):
- """Module used for grabbing random comments from pornhub's comment section.
- """
- self.url = 'https://www.pornhub.com/'
- data = requests.get(self.url)
- self.soup = BeautifulSoup(data.text, 'lxml')
- def get_rand_video(self):
- """Returns url of a random video from the hot section
- """
- hot_section = self.soup.find('ul', id='hotVideosSection')
- return self.url[:-1] + choice([section.div.div.a['href'] for section in hot_section.find_all(
- 'li', class_='js-pop videoblock videoBox')])
- def get_rand_comment(self, url=None, comment_len=(1, 50)):
- """Returns a random comment from a random video and removes any non-alphabetical characters.
- :param url:
- Link to a video source on pornhub.
- :param comment_len:
- A set of numbers to determine the length of a comment from minimum length to max length.
- :return:
- random comment parsed from the comment section of a video.
- """
- _min, _max = comment_len
- if _min > _max:
- raise ValueError('Minimum length cannot exceed Max length for the parameter, comment_len.')
- while True:
- if url is None:
- url = self.get_rand_video()
- data = requests.get(url)
- soup = BeautifulSoup(data.text, 'lxml')
- filtered_comments = [com for comment in soup.find_all('div', class_='commentMessage')
- if (com:=filter_comment(comment.span.text, comment_len)) is not None]
- if not filtered_comments:
- print(f"Could not find a comment within the range of {_min} and {_max} for this video.\n If this prompt "
- f"consists, consider widening the range for the '{Comment.get_rand_comment.__code__.co_varnames[2]}' "
- f"parameter in the module, '{Comment.__name__}'")
- if ask_player('Would you like to find another video? '):
- continue
- return
- return choice(filtered_comments)
- def filter_comment(comment='', comment_len=()):
- """Strips a comment of all it's dignity.
- :param comment:
- A comment to be filtered from all non-alphabetical characters
- :param comment_len:
- A range from a set of numbers in a tuple or a list, which determines the length of the comment after
- it has been filtered.
- :return:
- Return the filtered comment if it's within the given range in comment_len. Otherwise, return None.
- """
- _min, _max = comment_len
- filtered_comment = ''.join([char for char in comment if char in ascii_letters + ' ']).strip()
- if _min < len(filtered_comment) < _max:
- return filtered_comment
- def ask_player(prompt):
- """Ask the player if he/she would like to play.
- :param prompt:
- The message to be prompted to the user for questioning.
- :returns: Boolean
- """
- while True:
- if (play := input(f"{prompt} [Y/N]: ").lower()) in ['yes', 'y', '1']:
- return True
- if play in ['no', 'n', '2']:
- return False
- print('Invalid input. Please try again.')
- def main(prompt_vid=False):
- """Loops a game of a hangman.
- :param prompt_vid:
- If True, ask the player to open the related video to the default web browser after a game.
- :return: None
- """
- getter = Comment()
- while ask_player("Would you like to play Hangman?"):
- print('Fetching Comment...')
- random_video = getter.get_rand_video()
- rand_comment = getter.get_rand_comment(random_video, (5, 50))
- Hangman(rand_comment).play()
- if prompt_vid:
- if ask_player('Would you like to open the video in your web browser?'):
- webbrowser.open(random_video)
- sys.exit(0)
- if __name__ == '__main__':
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement