Hướng dẫn hangman game python github - trò chơi treo cổ python github

"""Runs a Hangman game that can be played via terminal. Prerequisites: 1. Download the code as hangman.py into any folder. 2. Get a .txt file called 'words.txt' with all the words that you want to include in the game. >> Example: https://github.com/dwyl/english-words To play: - Run `python hangman` This Hangman game features: 1. A simple interactive system that asks user for input for each letter and game. 2. A simple visual interfece that draws the hangman as the game progresses. 3. A simple scoring system that keeps track of the wins and losses. 4. Capability to change the words for any desired ones. 5. Capability of choosing level of difficulty based on a custom algorithm. 6. A custom algorithm that classifies words based on the probability of the letters and the repetition of them. """ import csv import random # Available letters. Selected English alphabet. # Modify based on your language. LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' # Frequency of letters on a word in English. # Obtained from: https://en.wikipedia.org/wiki/Letter_frequency # Modify based on your language. LETTER_PROBABILITY = { 'A': 8.167, 'B': 1.492, 'C': 2.782, 'D': 4.253, 'E': 12.70, 'F': 2.228, 'G': 2.015, 'H': 6.094, 'I': 6.966, 'J': 0.153, 'K': 0.772, 'L': 4.025, 'M': 2.406, 'N': 6.749, 'O': 7.507, 'P': 1.929, 'Q': 0.095, 'R': 5.987, 'S': 6.327, 'T': 9.056, 'U': 2.758, 'V': 0.978, 'W': 2.360, 'X': 0.150, 'Y': 1.974, 'Z': 0.074, } class Hangman(object): """Hangman game.""" def __init__(self): """Initializes hangman game. Loads words into memory, restarts scores and kicks off game by allowing user to select difficulty level. """ self._game_words = self._load_words() self._selected_words = set() self._wins = 0 self._loses = 0 self._select_difficulty() def _get_difficulty_input(self): """Requests and gets difficulty level from user. Returns: Input from user to difficulty prompt. """ difficulty = input('Select your difficulty: [E]asy, [M]edium, [H]ard\n') return difficulty.upper() def _ask_difficulty(self): """Gets difficulty level from user, and validates user input. Returns: Input from user to difficulty prompt. Validated input must be: E, M, H. """ difficulty = self._get_difficulty_input() while difficulty not in ('E', 'M', 'H'): print( 'Type E for Easy words. ' 'Type M for Medium words. ' 'Type H for Hard words. ' ) difficulty = self._get_difficulty_input() return difficulty def _select_difficulty(self): """Aks difficulty from user, and selects the set of words for the given difficulty. After selecting difficulty, starts the game. """ difficulty = self._ask_difficulty() if difficulty == 'H': self._words = self._game_words['hard'] elif difficulty == 'M': self._words = self._game_words['medium'] else: self._words = self._game_words['easy'] self._print_game_words() self._start_game() def _get_word_difficulty(self, word): """Gets the difficulty of a word. This implements a custom algorithm to determine the difficulty of a word based on: - its length. - the frequency of each letter. - the ratio of repeated letters. If word is too short or a plural, word gets excluded. Args: word: Word for which to obtain difficulty. Returns: Difficulty of the word: easy, medium, hard. """ word_length = len(word) if word_length < 5: return None if word[-1] == 'S': return None word_unique_characters = set(list(word)) unique_character_count = len(word_unique_characters) repeated_letters = word_length - unique_character_count repeated_ratio = (repeated_letters / word_length) + 1 unique_ratio = unique_character_count / word_length probability = 0 for unique_character in word_unique_characters: if unique_character not in LETTERS: return None count_letters = word.count(unique_character) letter_probability = LETTER_PROBABILITY.get(unique_character, 0) / 100 probability += letter_probability probability = probability difficulty = probability / unique_ratio if difficulty < 0.25: return 'hard' elif difficulty < 0.4: return 'medium' else: return 'easy' def _load_words(self): """Load words from words.txt into memory. Classifies each word into several difficulties. Returns: Dictionary containing a list of words for each difficulty. """ with open('words.txt', 'rt') as dictionary: words = csv.reader(dictionary, delimiter=',') game_words = { 'easy': [], 'medium': [], 'hard': [], } for word_line in words: word = word_line[0].upper() difficulty = self._get_word_difficulty(word) if difficulty: game_words[difficulty].append(word) return game_words def _print_game_words(self): """Prints length and sample words for each difficulty. Used for debugging purposes only. """ print( 'E', len(self._game_words['easy']), self._game_words['easy'][0:5], '\n\n\n' 'M', len(self._game_words['medium']), self._game_words['medium'][0:5], '\n\n\n' 'H', len(self._game_words['hard']), self._game_words['hard'][0:5], '' ) def _choose_random_word(self): """Chooses a random word from the available set. Returns: Randomly selected word. """ selected_index = random.randint(0, len(self._words) - 1) return self._words[selected_index] def _select_word(self): """Selects a random word that was not previously selected. Returns: Randomly selected word. Validation ensures not repeated within current game. """ word = self._choose_random_word() while word in self._selected_words: word = self._choose_random_word() return word def _get_letter_input(self): """Gets next letter for game from user. Returns: Input from user upon letter prompt. """ letter = input('Choose a letter: ') return letter.upper() def _ask_for_letter(self): """Asks and validates next letter from user. Rejects input if: - not just one letter. - letter was already selected. - invalid letter, not in selected set. Returns: Letter selected by user for current round. Validation guarantees requisites. """ letter = self._get_letter_input() while len(letter) > 1: print('Must select one letter only.') letter = self._get_letter_input() while letter not in self._available_letters: print('Letter {} was already chosen.'.format(letter)) letter = self._get_letter_input() return letter def _update_available_letters(self, letter): """Updates available letters to select for current round. Args: letter: Selected letter that will be taking off the available letters. """ letter_position = self._available_letters.index(letter) if letter_position > -1: del self._available_letters[letter_position] def _get_word_progress(self): """Generates a text showing the current round word progress. Returns: String showing the word progress. Example: p _ t a t _ """ word_display = '' for character in self._selected_word: if character in self._selected_letters: word_display += character.upper() + ' ' else: word_display += '_ ' return word_display def _get_hangman(self): """ Generates a text showing the hangman progress of the current round. Returns: String showing the hangman progress. Example (full hangman): |‾‾‾‾‾| | O | /|\ | / \ | ‾‾‾‾‾‾‾‾‾‾ """ hangman = """ |‾‾‾‾‾| | {head} | {left_arm}{body}{right_arm} | {left_leg} {right_leg} | ‾‾‾‾‾‾‾‾‾‾ """.format( head='O' if self._mistakes > 0 else ' ', left_arm='/' if self._mistakes > 1 else ' ', body='|' if self._mistakes > 2 else ' ', right_arm='\\' if self._mistakes > 3 else ' ', left_leg='/' if self._mistakes > 4 else ' ', right_leg='\\' if self._mistakes > 5 else ' ', ) return hangman def _update_game_status(self, letter): """Updates game status for current game. Adds one extra round. Updates word progress. Updates hangman progress. Updates selected and available letters for round. Updates win/lose game status. Args: letter: Currently selected letter. """ self._rounds += 1 if letter not in self._selected_word: self._mistakes += 1 else: self._correct_letters += self._selected_word.count(letter) self._selected_letters.append(letter) self._update_available_letters(letter) self._is_lose = self._mistakes >= 6 self._is_win = self._correct_letters >= len(self._selected_word) def _print_game_status(self): """Prints current game status to terminal. Prints: - hangman progress. - word progress. - number of rounds played on current word. - chosen letters. - available letters. """ hangman = self._get_hangman() word_display = self._get_word_progress() print('\n\n\n') print(hangman) print('Round: {}'.format(self._rounds)) print('Word: ', word_display) print('Chosen letters:', ' '.join(self._selected_letters)) print('Available letters: ', ' '.join(self._available_letters)) def _get_new_game_input(self): """Asks user whether they want to continue playing. Returns: User input on whether to continue playing. """ play_again = input('Do you want to play again? [Y]es, [N]o\n') return play_again.upper() def _ask_new_game_input(self): """Asks user and validates whether they want to continue playing. Returns: User input on whether to continue playing. Validation ensures output to be Y or N. """ play_again = self._get_new_game_input() while play_again not in ('Y', 'N'): print( 'Type Y if you want to play again. ' 'Type N if you do not want to play again. ' ) play_again = self._get_new_game_input() return play_again def _ask_for_new_game(self): """Prints game results and asks for new game. Prints: - Current round result (win or loss). - Total wins and total losses. """ print('\n\n\n') if self._is_win: self._wins += 1 print('CONGRATULATIONS! You guessed: {}'.format(self._selected_word)) elif self._is_lose: self._loses += 1 print('GAME OVER! The word was: {}'.format(self._selected_word)) print('Wins: {} / Loses: {}'.format( self._wins, self._loses )) play_again = self._ask_new_game_input() if play_again == 'Y': self._start_game() def _set_up_new_game(self): """Set ups a new word round. - Selects a new word. Adds word to selected words. - Resets selected and available letters. - Resets counters of rounds and mistakes. - Resets end status (is_win / is_lose). """ self._selected_word = self._select_word() self._selected_words.add(self._selected_word) self._selected_letters = [] self._available_letters = list(LETTERS) self._correct_letters = 0 self._rounds = 0 self._mistakes = 0 self._is_win = False self._is_lose = False def _play_round(self): """Executes one letter round. - Asks user for new letter. - Updates game progress. - Prints game progress. """ letter = self._ask_for_letter() self._update_game_status(letter) self._print_game_status() def _start_game(self): """Manages hangman game rounds. - If round is completed: asks for new game. - If round is not completed: asks for new letter. """ self._set_up_new_game() self._print_game_status() while not self._is_win and not self._is_lose: self._play_round() else: self._ask_for_new_game() game = Hangman()