В этом проекте мне было поручено создать простую консольную игру на Python, используя то, что я узнал из Codecademy CS101. Я решил включить модуль преобразования речи в текст вместе с циклами (for/while) и операторами if/elif/else для управления потоком и методами для работы с поступающими данными. Все, чтобы воссоздать поведение игры, как в реальной жизни. Я использовал простые для понимания библиотеки, такие как pyttsx3 и SpeechRecognition, потому что, если они вписывались в рамки программы и документации, было очень легко следовать.

Во время проекта я, конечно, столкнулся с некоторыми трудностями. Самая первая проблема, с которой я столкнулся, заключалась в поиске в списке пары одинаковых элементов. В случае с этой игрой нахождение двух и более одинаковых букв в слове. Сначала я решил эту проблему, столкнувшись с этой проблемой с помощью циклов, вложенных циклов и набора операторов if. Проделав это в течение некоторого времени и нарисовав список, чтобы получить представление о том, чего я пытаюсь достичь, я все еще не мог взломать код. Поэтому я обратился к Google, который указал мне на StackOverflow. Мне дали ответ и объяснение, которое я понял, но оставил с горечью, потому что очень хотел решить это сам. Я даже начал решать проблему на бумаге, прежде чем писать код. Итак, я пришел к выводу, что мне чего-то не хватает в моих нынешних знаниях о программировании. Я считаю, что это то, что будет дальше после Codecademy CS101, то есть Codecademy CS102 Data Structures and Algorithms. Я так готов к этому! Ниже вы найдете описание каждого файла и объяснение каждой строки кода в файлах.

Ссылка на Github Repo: https://github.com/dapierrot21/stt-hangman-console

Класс игрока

import pyttsx3
import speech_recognition as sr  # speech recogniton.


class Player:
    engine = pyttsx3.init()
    engine.setProperty('rate', 75)

    def __init__(self, name):
        self.name = name

    def speak(self, text):
        self.engine.say(text)

    def take_command(self):
        r = sr.Recognizer()
        with sr.Microphone() as source:
            print("\n")
            print("Remember to use a word instead of a letter.")
            print("Ex: For letter \"c\" -> try saying \"cat\"")
            print("Speak your word now.")
            # Recommended for situations where the ambient noise level is unpredictable, which seems to be the majority of use cases. If the ambient noise level is strictly controlled, better results might be achieved by setting this to False to turn it off.
            r.dynamic_energy_threshold = True
            r.energy_threshold = 4
            r.adjust_for_ambient_noise(source, duration=0.5)
            r.pause_threshold = 4
            audio = r.listen(source, phrase_time_limit=9, timeout=10)
            statement = ""
            try:
                statement = r.recognize_google(audio, language='en-US').lower()
                print(f"You said: {statement[0]}\n")

            except sr.UnknownValueError:
                print("Sorry I could not hear you.")
            except sr.RequestError as e:
                print("Request Failed; {0}".format(e))
            return statement[0]
  • Переменные класса — значения, которые я не хочу менять.
  • Я создал объект преобразования речи в текст и присвоил его переменной с именем engine.
  • Доступ и установка свойства скорости на 75, чтобы придать голосу более плавный звук.
  • init — переменные экземпляра.
  • name — при создании класса Player. Вам нужно будет предоставить элемент. В данном случае это строка вашего имени.
  • speak(text) — принимает строку: None
  • используя функцию say из объекта преобразования речи в текст, который произносит заданную строку, переданную ему.
  • take_command() — возвращает строку: str
  • Распознаватель() и Микрофон() используются для получения звука с помощью микрофона игрока.
  • Затем у меня есть несколько строк, которые выводятся на консоль и объясняют, как лучше всего захватить целевое письмо.
  • Следующие 5 строк обращаются к свойствам объекта Recognizer() и задают для них значения, чтобы создать идеальные настройки для получения четких ответов от игрока независимо от фонового шума. Я также даю достаточно времени, чтобы сказать письмо.
  • Я использую recognize_google() для получения письма
  • Наконец, я ловлю любые ошибки и, если их нет, возвращаю первую букву оператора, используя нарезку. Каким должно быть целевое письмо от игрока.

Класс палача

import datetime
from random_word import RandomWords
from PyDictionary import PyDictionary


class Hangman:

    def __init__(self):
        self.wrong_guesses = []
        self.random_word = self.create_random_word()
        self.correct_letters = []
        self.letters_for_random_word = [letter for letter in self.random_word]
        self.place_holder_for_correct_letters = [
            [] for word in self.random_word]

    # Creates random word
    def create_random_word(self):
        r = RandomWords()
        word = r.get_random_word()
        return word

    def meaning_of_word(self, word):
        try:
            py = PyDictionary()
            meaning_of_word = py.meaning(
                word, disable_errors=True)
        except None:
            return "Sorry having trouble finding the meaning of this word. Good luck."
        return meaning_of_word

    def check_player_letter(self, player_guess):
        if player_guess in self.wrong_guesses:
            print("You already choose this letter.")

        elif player_guess not in self.letters_for_random_word:
            self.wrong_guesses.append(player_guess)
        else:

            indices = [i for i, x in enumerate(
                self.letters_for_random_word) if x == player_guess]

            for index in indices:
                if player_guess in self.place_holder_for_correct_letters[index]:
                    print("Letter is already in place.")
                else:
                    self.place_holder_for_correct_letters[index] += player_guess
                    self.correct_letters.append(player_guess)

    def greeting_of_the_day(self, name):
        hour = datetime.datetime.now().hour
        if hour >= 0 and hour < 12:
            print("Hello,Good Morning {player_name}!".format(
                player_name=name))
        elif hour >= 12 and hour < 18:
            print("Hello,Good Afternoon {player_name}!".format(
                player_name=name))
        else:
            print("Hello,Good Evening {player_name}!".format(
                player_name=name))
  • init — переменные экземпляра.
  • wrong_guesses — это пустой список, в котором будут храниться все неверные варианты букв, выбранные игроками.
  • random_word — это переменная, которая содержит слово, возвращаемое методом create_random_word в классе Hangman.
  • correct_letters — это пустой список, который будет содержать правильно выбранные буквы и использоваться позже в программе для проверки, угадал ли игрок слово.
  • буквы_для_случайного_слова — это генератор списка, который содержит буквы случайного_слова для циклического прохождения.
  • place_holder_for_correct_letters — это понимание списка, которое содержит длину пробелов, которые содержит random_word. Это используется позже, чтобы поместить букву в точное место индекса.
  • meaning_of_the_word(). Эта функция предназначена для определения некоторых случайных_слов, которые будут даны вам в этой игре. Поэтому я подумал, что знание значения этого слова сделает игру более приятной. Функция meaning() из объекта PyDictionary берет слово и возвращает значение этого слова.
  • create_random_word() — возвращает одно слово: str
  • Создает объект RandomWords
  • Используйте этот метод объекта, чтобы получить случайное слово
  • Затем возвращает одно слово.
  • check_player_letter() — ничего не возвращает: None
  • Сначала проверяется переменная player_guess, чтобы определить, входит ли она в список wrong_guesses. Если да, напишите игроку, что он уже выбрал эту букву.
  • Если буквы нет в списке letters_for_random_word, добавьте эту букву (player_guess) в список wrong_guesses.
  • Теперь, если письмо прошло через контрольные точки (операторы if/elif), итератор enumerate(self.letters_for_random_word)выдает пары (index, item) для каждого элемента в списке. Использование переменной цикла i, xas target для распаковки этих пар в индекс iи элемент списка x. Мы фильтруем все x, соответствующие нашему критерию, и выбираем индексы iэтих элементов. Мы храним пару или пары в индексах переменных. Вот ссылка, которая меня спасла. Как найти все вхождения элемента в список
  • Затем запустите цикл for для этих пар или пар индексов и назначьте player_guess правильное место в place_holder_for_correct_letters, который представляет собой список, отражающий размер буквы, которую вы пытаетесь найти. заполнить.
  • Наконец, мы добавляем player_guess в список correct_letters. Этот список используется для управления ходом игры.
  • greeting_of_the_day() — ничего не возвращает: None
  • Захватите час дня и назначьте его переменной часа.
  • В зависимости от часа дня распечатать игроку правильное приветствие времени суток.

Класс игры

from player import Player
from hangman import Hangman


if __name__ == "__main__":
    player = Player('Dean')
    hangman = Hangman()

    number_of_guesses = len(hangman.random_word)
    count = 0  # is going to be the sum of the len(wrong_guess).

    while count < number_of_guesses:

        hangman.greeting_of_the_day(player.name)
        print("Welcome to Speech-to-Text Hangman Console Game.")
        print("Letters like \"c\", \"u\", \"a\", \"h\" can sound like a word and not the letter your trying.")
        print("So tackle this problem I suggest that you use word instead of letter.")
        print("Ex: Letter \"c\" is best heard when \"cat\" is said.")
        print("\n")

        print("The number of guesses you have is based on the length of the word.")
        print("The word contains {space} letters. So you have {space} chances of getting the word correct".format(
            space=len(hangman.place_holder_for_correct_letters)))
        print(hangman.place_holder_for_correct_letters)
        print("\n")

        print("Now let\'s guess a letter. I suggest using a word that has the target letter as the first letter in that word.")

        while count != number_of_guesses:
            print("Meaning of the word: {meaning}".format(
                meaning=hangman.meaning_of_word(hangman.random_word)))
            letter = player.take_command()
            hangman.check_player_letter(letter)
            if len(hangman.correct_letters) == len(hangman.letters_for_random_word):
                print("Congrats! you have won. The word is {word}.".format(
                    word=hangman.random_word))
                break
            else:
                if letter in hangman.letters_for_random_word:
                    print(hangman.place_holder_for_correct_letters)
                    print("Correct! {letter} is within the random word.".format(
                        letter=letter))
                    print("You have {guesses} guesses left.".format(
                        guesses=number_of_guesses - count))

                if letter in hangman.wrong_guesses:
                    print(hangman.place_holder_for_correct_letters)
                    print("Wrong letters: {wrong_letters}".format(
                        wrong_letters=hangman.wrong_guesses))
                    count += 1
                    print("You have {guesses} guesses left.".format(
                        guesses=number_of_guesses - count))
  • В этом файле находится игровая логика.
  • Затем создаются объекты Hangman() и Player(), и оба они назначаются переменным.
  • Переменные number_of_guesses и count используются для управления ходом игры на основе количества оставшихся догадок, а также момента окончания игры.
  • Внешний цикл while будет продолжать работать до тех пор, пока переменная count меньше, чем длина wrong_guesse в списке.
  • Игрока приветствует соответствующее время суток и имя, присвоенное объекту Player при первом создании объекта.
  • Далее идет строка строки, которая будет напечатана на консоли, объясняя игру и сообщая вам длину слова, которая также является количеством шансов, которые вы должны угадать каждое слово.
  • У меня напечатан список place_holder_for_correct_letters, чтобы показывать текущий список после каждой попытки ввести слово. Это будет включать все правильные буквы из предыдущих догадок.
  • Вложенный цикл while будет продолжаться до тех пор, пока счетчик не будет равен количество предположений.
  • Далее распечатывается значение слова, если для этого слова нет значения, которое можно было бы найти. None возвращается.
  • Элемент, возвращаемый из take_command(), который будет первой буквой слова, заданного игроком с помощью нарезки.
  • Затем это письмо передается в check_player_letter() из класса Hangman. Который не возвращает ничего, кроме запуска проверки письма и присвоения букв там, где они должны быть.
  • Наконец, пара операторов if/elif/else проверяет, выиграл ли игрок, если да, то на этом цикл завершается, прибавляется 1 к счету, если буква неверна. Игра также закончится, если у игрока закончатся догадки.

Заключение

Цель этого блога — продемонстрировать эту программу и рассказать о некоторых проблемах, с которыми я столкнулся при ее создании. Я также многое узнал о себе, создавая эту «простую игру». Надеюсь, вам понравилось читать этот блог и читать мой код. Если у вас есть какие-либо предложения о том, как я могу улучшить свой код и / или свои навыки ведения блога, ваши советы действительно приветствуются. Спасибо за прочтение. До следующего раза!