Как нарисовать виселицу буквами и знаками
Перейти к содержимому

Как нарисовать виселицу буквами и знаками

  • автор:

Объектная «Виселица» v.2

В этом уроке мы будем использовать наши знания о классах в деле и перепишем с их помощью игру «Виселица».

Мы напишем вторую версию игры, разбив программу на два класса Game и ResultPrinter . Узнаем как работает оператор case в Ruby, как создавать поля класса (переменные экземпляра) и немного о спецсимволах и псевдографике.

План урока

  1. Переделываем структуру программы «Виселица»
  2. Добавляем к выводу результата изображение виселиц

Новая виселица!

Деление программы на классы

Удобство деления программы на классы легко продемонстрировать на таком примере: у топора есть древко, а есть металлическое лезвие. Если лезвие топора снять и закрепить на древке ударную часть молотка, получится молоток (замечание для плотников, которые будут читать этот текст: конечно, получится лишь жалкое подобие молотка, это просто для примера).

Молотки, топоры

Древко — это экземпляр класса ручка, который может работать с разными экземплярами класса насадка: лезвие топора или ударная часть молотка.

Вы, наверное, неоднократно видели отвёртки с набором насадок для различных шурупов и винтов.

Универсальная отвёртка

В такой ситуации можно сказать, что держатель отвёртки является экземпляром класса «основание», а каждая насадка — экземпляром класса «насадка». Удобство в том, что класс «основание» ничего не знает о том, какие болты будут с его помощью закручивать, зато он может уметь, например, фиксировать вращение только в одну сторону, для удобства работы.

Если вдруг изобретут насадку в форме звёздочки, вам не придётся выкидывать «основание» такой отвёртки. Вам просто надо будет найти соответствующую насадку.

В то время класс «насадка» совершенно ничего не знает про то, с каким основанием он будет работать: оно может быть длинным, коротким, угловым, это вообще может быть дрель-шуруповёрт.

Задумайтесь. Каждая деталь фактически становится самостоятельным инструментом, который хоть и бесполезен без своей «второй половинки», но является универсальным для всех таких половинок. Это удобно.

Делим «Виселицу» на классы

Грубо говоря, все методы нашей виселицы v.1 по факту занимаются двумя вещами:

Меняют состояние игры

  • get_letters
  • get_user_input
  • check_input

Выводят что-то на экран (или чистят его)

  • get_word_for_print
  • print_status
  • cls

Это-то наталкивает нас на мысль, что игра по факту состоит из двух глобальных частей: «внутренность игры» и «интерфейс вывода». Отделим вывод информации для игрока от внутренней игровой логики. В действительности, методов окажется немного больше, но не пугайтесь, мы всё объясним.

Класс Game

В первой части (игра) у нас будет всё, что связано с состоянием игры: загаданное слово, отгаданные буквы, буквы, которых в слове не оказалось и количество ошибок будут полями (переменными экземпляров) класса Game.

Для этого класса создадим отдельный файл: game.rb (как обычно, в новой папке урока c:\rubytut\lesson12 ).

А методы get_user_input и check_input мы соберём в один метод ask_next_letter .

Итак, поехали, повторяем логику программы.

class Game # тут будет описание класса Game end 

Метод initialize

Конструктор класса Game у нас будет вызывать метод get_letters (так как игра начинается с загадывания слова и без этого слова мы не можем продолжать игру). Так как метод get_letters принадлежит тому же классу Game , в конструкторе нет необходимости писать Game.get_letters , достаточно написать просто get_letters . Это верно для всех методов класса Game , вызываемых из других методов класса Game .

def initialize(slovo) @letters = get_letters(slovo) @errors = 0 @good_letters = [] @bad_letters = [] @status = 0 end 

Заметьте, мы ждём в конструкторе параметр slovo (да, конструктор — это обычный метод, и в него тоже можно передать параметр).

Game.new("жираф") 

нам нужно будет в скобках указать загаданное слово, чтобы игра началась, а слово сохранилось в переменной letters нового экземпляра класса Game . Обратите также внимание на новое поле @status , оно нам понадобится в дальнейшем.

Метод get_letters

def get_letters(slovo) if (slovo == nil || slovo == "") abort "Для игры введите загаданное слово в качестве аргумента при запуске программы" end return slovo.split("") end 

Как и в старой версии, этот метод принимает на вход строчку с загаданным словом, проверяет, есть ли в этой строчке что-нибудь и если там пусто, заканчивает программу, сообщив об этом пользователю.

Если же там что-то есть, он разбивает слово на буквы уже знакомым нам способом и возвращает получившийся массив конструктору, чтобы тот мог его записать в поле класса letters .

Метод ask_next_letter

def ask_next_letter puts "Введите следующую букву" letter = "" while letter == "" do letter = STDIN.gets.encode("UTF-8").chomp end next_step(letter) end 

Мы немного переименовали метод get_user_input , чтобы было понятнее, что именно он делает. Он не просто берёт то, что ввёл пользователь, а именно спрашивает следующую букву. Всегда старайтесь называть ваши классы и методы максимально точно.

В нём мы спрашиваем у пользователя букву и добиваемся, чтобы он её-таки ввёл (в цикле проверяя, не ввёл ли он пустоту), а потом вызываем метод next_step , который эту букву обработает, как надо. Обратите внимание, опять внутренний метод класса мы вызываем без упоминания самого класса (не пишем Game. перед названием метода).

Метод next_step

Метод next_step по сути, самый важный, он передвигает состояние игры на следующий шаг, проверяя букву в слове.

def next_step(bukva) if @status == -1 || @status == 1 return end if @good_letters.include?(bukva) || @bad_letters.include?(bukva) return end if @letters.include? bukva @good_letters = 7 @status = -1 end end end 

Этот метод очень похож на наш старый метод check_input с той лишь разницей, что все данные он берёт не из параметров, а из полей класса.

Это ещё одно удобство классов: они хранят нужные для их методов данные в полях, рядом с этими же методами, не загромождая ими остальные части вашей программы.

Обратите внимание, также, что этот метод ничего не возвращает, он просто меняет состояние поля @status (вот оно нам и пригодилось), это ещё одно удобство: методам класса Game не надо ничего возвращать, они просто меняют поля класса Game .

Методы-геттеры

Ещё одна особенность классов заключается в том, что они «прячут» переменные своих экземпляров от чужих глаз. Если у нас в программе будет экземпляр класса Game

game = Game.new('слово') 

То мы не сможем достать переменные экземпляра game ( @status , например) просто так (нельзя просто взять и написать game.@status — будет ошибка). Зачем так придумали мы сейчас рассказывать не будем, важно лишь то, что нам нужно научиться доставать значения переменных для экземпляров класса Game .

Для этого нам надо также написать 5 так называемых геттеров (не путать с гетрами) — методов класса Game , которые просто возвращают значения соответствующих полей класса, чтобы ими можно было пользоваться из основной программы:

def status return @status end def errors return @errors end def letters return @letters end def good_letters return @good_letters end def bad_letters return @bad_letters end 

Для каждого поля класса мы написали метод, который, будучи вызванным у экземпляра этого класса, возвращает значение одноимённой переменной класса.

Класс ResultPrinter

Теперь переходим ко второй части нашей программы: выводу информации на экран. Этим будет заниматься класс ResultPrinter , который как и полагается новому классу, мы будем описывать в отдельном файле result_printer.rb .

Обратите внимание, что для названий классов мы используем CamelCase — написание словосочетаний без пробелов с увеличенной большой буквой каждого слова, а названия файлов этих классов мы пишем маленькими буквами, заменяя пробелы нижним подчёркиванием — это соглашение, принятое в сообществе Ruby, настоятельно советуем вам поступать также.

class ResultPrinter end 

Метод print_status

Первый и самый важный метод класса ResultPrinter будет заниматься выводом состояния игры на экран.

def print_status(game) cls puts "Слово: #" puts "Ошибки: #" if game.status == -1 puts "Вы проиграли :(" puts "Загаданное слово было: " + game.letters.join("") elsif game.status == 1 puts "Поздравляем, вы выиграли!" else puts "У вас осталось ошибок: " + (7 - game.errors).to_s end end 

Этот метод вызывается каждый раз, когда нам нужно обновить картинку для игрока — показать ему новую виселицу.

Во-первых, этот метод чистит экран с помощью метода cls , который тоже, конечно же, логично сделать частью класса ResultPrinter (если вы забыли, как он работает — вспомните).

def cls system "clear" || system "cls" end 

Во-вторых, он не может просто взять данные из полей объекта класса Game . Ему нужно передать этот объект, а уже состояние игры наш ResultPrinter сам возьмет из объекта Game с помощью геттеров.

Ну и в-третьих, здесь описан вспомогательный метод get_word_for_print , чтобы напечатать слово с закрытыми неразгаданными буквами (как в «Поле чудес»):

def get_word_for_print(letters, good_letters) result = "" for item in letters do if good_letters.include?(item) result += item + " " else result += "__ " end end return result end 

Основная программа viselitsa.rb

Самое время написать нашу программу с использованием новых классов Game и ResultPrinter : пора взять основание отвёртки, насадить на него наконечник и закрутить парочку шурупов, Дамы и Господа!

Сперва нам надо наши классы подключить:

require_relative "game" require_relative "result_printer" 

Теперь создадим по экземпляру каждого класса. ResultPrinter создаём просто вызвав у него new (у него даже конструктора нет, ничего страшного, так можно), а вот для игры нам нужно получить слово.

Обратите внимание, классу game абсолютно плевать, откуда мы возьмём это слово, главное чтобы мы передали его конструктору. А берём мы слово как обычно из строки запуска и передаём его в конструктор класса Game .

slovo = ARGV[0] if (Gem.win_platform? && ARGV[0]) slovo = slovo.dup .force_encoding("IBM866") .encode("IBM866", "cp1251") .encode("UTF-8") end game = Game.new(slovo) printer = ResultPrinter.new 

Время запустить основной игровой цикл. Условием выхода из цикла будет смена статуса игры ( game.status , не забываем, что у нас есть такой метод-геттер), который изначально равен 0 (прописали в конструкторе).

Теперь мы знаем, что как только @status в нашем объекте game (не путать с классом Game ) станет отличным от 0, мы выйдем из цикла и закончим работу программы. В цикле мы выводим текущее состояние игры на экран и спрашиваем новую букву у игрока:

while game.status == 0 do printer.print_status(game) game.ask_next_letter end 

Обратите внимание, насколько ёмким теперь выглядит тело цикла. Вся сложность ушла туда, где ей и суждено быть — во внутреннюю логику методов классов Game и ResultPrinter .

После цикла нам только ещё раз нужно написать результат и вуаля! Программа готова! Дальше всё произойдёт само, программа стала простой и ясной. Не бойтесь ошибок и опечаток, как с ними бороться мы рассказывали в 3-м уроке. Если что-то не получается, скачайте наши исходники этих файлов и внимательно посмотрите их.

Теперь программу можно запустить:

cd c:\rubytut\lesson12 ruby viselitsa "космонавт" 

Визуализация результата

Теперь продемонстрируем еще одну крутую вещь, которую нам помогут сделать классы.

Мы поменяем метод print_status класса ResultPrinter , добавив туда псевдографику — картинку, составленную из текстовых символов, тире, подчёркиваний, скобочек и прочего.

Все остальные части нашей программы, а именно, код основной её части viselitsa.rb и код класса Game останется прежним.

Метод print_viselitsa

А в класса ResultPrinter добавим новый достаточно громоздкий метод для отрисовки картинки виселицы в зависимости от количества ошибок (вы не пугайтесь, он только выглядит страшно):

def print_viselitsa(errors) case errors when 0 puts " _______ |/ | | | | | | | __|________ | | " when 1 puts " _______ |/ | ( ) | | | | | | __|________ | | " when 2 puts " _______ |/ | ( ) | | | | | | | __|________ | | " when 3 puts " _______ |/ | ( ) | |_ | \\ | | | | __|________ | | " when 4 puts " _______ |/ | ( ) | _|_ | / \\ | | | | __|________ | | " when 5 puts " _______ |/ | ( ) | _|_ | / | \\ | | | | | __|________ | | " when 6 puts " _______ |/ | ( ) | _|_ | / | \\ | | | / \\ | / \\ | __|________ | | " when 7 puts " _______ |/ | | (_) | _|_ | / | \\ | | | / \\ | / \\ | __|________ | | " end end 

Ему нужно только передать в качестве параметра количество ошибок. Лучше всего скопировать этот метод из материалов к уроку, так как написать псевдографику с нуля довольно муторно:

Обратите внимание, что вместо одного обратного слеша \ мы пишем два \\ , это так называемые спец-символы. Например, символ переноса строки тоже начинается со слеша: \n , так Ruby (и не только Ruby, это во многих языках верно) понимает, что эта n (что после слеша) — не просто буква n, а именно перенос строки.

Если же мы хотим напечатать просто обратный слеш \ , как он есть, то Ruby может подумать, что мы хотим начать таким образом какой-то спец-символ, поэтому умные программисты добавили спец. символ, который просто выводит обратный слеш: \\ . Просто запомните это. Пригодится.

Оператор case

В нашем методе print_viselitsa мы использовали конструкцию case-when , которая очень удобна, когда у нас есть переменная и много (больше 2-х) вариантов развития событий в зависимости от того, что в этой переменной находится. Если if-else это развилка, где всего два пути, то case — развилка где дорог может быть сколько угодно:

case fruit when 'banana' puts "Это банан" when 'apple' puts "Это яблоко" when 'orange' puts "Это апельсин" else puts "Это какой-то непонятный фрукт" end 

Оператор case сравнивает значение выражения (в данном случае fruit) со всеми вариантами. Если в переменной fruit записана строка «banana» , то на экран выведется строчка

"Это банан" 

если в переменной fruit записана строка «apple» , то на экране окажется

"Это яблоко" 

если же в переменной fruit — «вишня» или вообще цифра 5 , то программа не выберет ни один из вариантов и пойдёт по варианту, который начинается со спец-слова default (по умолчанию, как аналог else ):

"Это какой-то непонятный фрукт" 

Запустите вашу новую виселицу и поиграйтесь с ней, глядя на новую псевдографику.

Если что-то не работает, то внимательно исправьте все ошибки, как мы учили вас в третьем уроке. Или возьмите наши исходники этой программы и внимательно их изучите.

И помните, что с первого раза (и даже с десятого) может не получиться даже у гениальных программистов. Ваша настойчивость в борьбе с трудностями и ошибками — это важнейшая часть вашего обучения. Чем труднее сейчас, тем проще будет потом. Поверьте, мы это проходили.

А в этом уроке мы попробовали классы в деле, разбив нашу программу Виселица на два класса Game и ResultPrinter , узнали, как работает оператор case , как пользоваться полями класса и немного узнали о спецсимволах и псевдографике.

В следующем уроке мы научимся открывать файлы в Ruby, читать их и выводить их содержимое на экран в различных формах.

Как нарисовать виселицу буквами и знаками

Следующая игра должна быть знакома всем. В классической игре с ручкой и бумагой, «Виселице», игрок должен угадать, какие символы используются в фразе. Если он угадывает букву, становятся видны все места ее включения во фразу. Если во всей фразе нет такой буквы, добавляется фрагмент рисунка с повешенным человеком. Если рисунок закончен прежде, чем фраза угадана, игрок проигрывает.

Цель проекта — воссоздать классическую игру «Виселица» в среде Flash. Игрок может с помощью клавиатуры угадывать буквы. Программа показывает буквы и рисует повешенного человека или, как в рассматриваемом примере, лису.

Рисунок 12.5 Игра «Виселица» проиграна

На рис. 12.5 изображен основной кадр игры, где рисунок с повешенной лисой закончен и открыты некоторые буквы. В данном случае игра только что была проиграна.

В игре производится множество действий с символами. Фраза, которую нужно угадать, представляет собой строку символов. Из нее вы создаете строку, в которой вместо букв находятся знаки подчеркивания. Это как раз то, что увидит пользователь.
Когда игрок угадывает букву, она сравнивается с каждой буквой исходной фразы. Если буква совпадает с какой-либо буквой фразы, она отображается на экране на своем месте (или местах).
Если игрок не угадывает, клип с лисой переходит к следующему кадру, в котором добавляется новый фрагмент изображения лисы. Если это последний кадр клипа с лисой, игра заканчивается.

Основной элемент — текстовое поле на экране. Сначала в нем находятся только пробелы и знаки подчеркивания, которые постепенно меняются на буквы, угадываемые игроком.
Текстовое поле должно быть динамическим и связано с переменной display . В панели Properties необходимо также выставить свойство Miltiline для текстового поля.
Текст отображается моноширинным шрифтом Monaco, который имеется в стандартной поставке системы Macintosh. Если вы создаете ролик в Windows, возможно, вам придется использовать другой моноширинный шрифт, например Courier New.

Для этой игры необходим моноширинный шрифт, чтобы независимо от того, сколько букв угадано, слова имели одинаковую длину. Если бы у букв была разная ширина, то при добавлении новых символов, которые больше или меньше знака подчеркивания, программе Flash пришлось бы заново перерисовывать текст.

Игре также необходим клип «actions», который реагирует на нажатие клавиш и передает информацию о нажатой клавише сценарию основной временной шкалы.

Основные фрагменты кода находятся в главной временной шкале, там всего три функции.
Первая определяет фразу в начале игры. Она проверяет все символы фразы и создает отображаемую строчку, состоящую из знаков подчеркивания. Именно такую строчку игрок видит в начале игры.

function initGame() < //
Задаем фразу,
phrase = «Imagination is more important than knowledge»;
// Создаем отображаемую строку.
display = «» ;
for (i = 0; i

// Рассавляем пробелы там, где нужно.
if (phrase.charAt(i) == » «) display = idsplay + » «;
> else // Заменяем буквы знаками подчеркивания,
display = display + «_»;>
>>

Функция charAt возвращает символ, расположенный на определенном месте в строке. Как во многих функциях языка ActionScript, первый символ располагается в позиции 0.

Каждый раз, когда пользователь нажимает клавишу, клип «actions» передает код символа в функцию makeGuess . Первое, что делает эта функция, — преобразовывает код в букву.
Переменная letter проверяется функцией isAlpha на соответствие какой-либо букве, то есть такие клавиши, как пробел иди клавиша с цифрой или другие, просто игнорируются. Более подробно мы рассмотрим функцию isAlpha позднее.
Затем функция makeGuess просматривает каждую букву, чтобы выяснить, совпадает ли она с выбранным символом, во время этого процесса заново формируется переменная display . Каждое найденное совпадение помешается в данную переменную, в которой уже содержатся те буквы, которые совпали ранее.

Функция fromCharCode получает число, например 65, и преобразует его в символ, такой как «А». У всех символов есть соответствующий код. Числа от 65 до 90 относятся к заглавным буквам. Числа от 97 до 122 — к прописным (имеется в виду английский алфавит); 32 обозначает пробел. Полный список символов и их кодов можно найти в документации по Flash.

Изначально переменной gotOne присваивается значение false . Если найдено хотя бы одно совпадение, оно изменяется на true . Если в конце цикла значение переменной все еще равно false , значит, игрок не угадал букву, и клип с изображением лисы переходит к следующему кадру.

Функция toUpperCase() берет любую строчку и преобразует все прописные буквы в заглавные. Эта функция очень полезна в таких ситуациях, когда вы хотите найти совпадающие буквы независимо от их регистра (работает она только для строк, содержащих буквы аиглийского алфавита).

function makeGuess(code) // Получаем символ, соответствующий нажатой клавише,
letter = String.fromCharCode(code);
// Проверяем, является ли символ буквой,
if (isAlpha(letter)) // Предполагаем, что буква не будет найдена.
gotOne = false;
// Начинаем заново отображать строку.
newDisplay = «»;
for (i=0;i

// Проверяем,( совпадают ли буквы.
if (phrase.charAt(i).toUpperCase() == letter.toUpperCase()) // Помещаем букву в отображаемый текст.
newDisplay = newDisplay +
letter.toUpperCase();
// Отмечаем найденное совпадение.
gotOne = true;
> else // ЕСЛИ совпадения не найдены,
// отображаем те же буквы.
newDisplay = newDisplay + display.charAt(i)>
> // Обновляем строку,
display = newDisplay;
// Если совпадения не найдены, добавляем
// еще один фрагмент в рисунок с лисой,
if (!gotOne) <
fox.mextFrame();
// Проверяем, вся ли лиса изображена,
if (fox._currentFrame ==8) gotoAndPlay(«lose»);
>
> else if (display == phrase.toUpperCase()) // Отображаемая строка совпадает с исходной,
// завершаем игру. gotoAndPlay(«win»);>
>
>

Функция isAlpha берет строчку и проверяет, является ли первый символ буквой или нет.
С помощью функции charCodeAt она получает код первой буквы. Так код для прописных букв на 32 больше, чем для заглавных, для любого кода, который больше 90, мы вычтем 32, чтобы проверять сразу же и прописные, и заглавные буквы.

Функция charCodeAt возвращает код любого символа строки. Единственный аргумент, который ей передается, — это местоположение символа То есть для первого символа следует записать charCodeAt (0).

// Запускаем утилиту для проверки,
// расположен ли символ в пределах от А до Z.
function isAlpha(letter) // Определяем код символа.
n = letter.charCodeAt(0) ;
// Преобразуем прописную буквы в заглавную.
if (n > 90) n -= 32;
// Проверяем, расположен ли символ в пределах от А до Z.
return ((n >= 65) and (n initGame . Однако можно загружать текст из внешних источников (как это сделать. вы узнали из предыдущих разделов этой главы), так будет проще изменять фразу. Вы даже можете использовать список фраз, которые будут отображаться одна за другой или в случайном порядке.
Если вы хотите включить в игру знаки пунктуации, следует изменить код, чтобы в начале игры кроме пробелов программа автоматически отображала и эти знаки. С помощью функции isAlpha можно проверить, является ли символ буквой, и если нет, то сразу его показать.

Игра «Виселица»

В классической игре «Виселица» ведущий загадывает слово и за каждую неверно названную игроком букву рисует часть человечка на виселице, таким образом игроку надо успеть отгадать слово до того, как рисунок будет закончен полностью. Такой негуманный вариант абсолютно не устраивал педагогов ДОУ, поэтому мы вместе придумали разнообразные сюжеты, в которых не формируется какая-то печальная композиция, а разрушается что-то позитивное, связанное с темой проекта. В остальном все похоже.

Виселица

Предлагаю вам скачать игру, это презентация PowerPoint в режиме демонстрации, состоящая из одного слайда. Скачайте архив и распакуйте файл *.ppsx.

Вся игра выполнена с помощью анимации, алгоритмы описаны в книге «Анимация в PowerPoint: путь к мастерству». Поскольку блог посвящен PowerPoint, то здесь мне хотелось бы указать принципиальные моменты, которые легко решаются с помощью «волшебного квадрата», копирования анимации и описанных в книге приемов, которые позволяют экономить время и не делать огромную работу по анимации 33 букв алфавита. Времени жалко всем, есть быстрые способы.

Пояснения к алгоритму построения игры в PowerPoint

Можно указать следующие «сложности» при прямолинейной реализации игры без применения предложенных в книге алгоритмов:

  1. Первая сложность – много букв. Из 33 букв алфавита, допустим, десяток участвует в загаданном слове. Можно создать одну букву алфавита и одну букву загаданного слова, наладить анимацию, далее копировать, а не делать анимацию для каждой буквы. Получится десяток букв алфавита и целое слово. С правильными буквами понятно. А вот щелчки по неправильным буквам, которых гораздо больше, должны приводить к поломке цветочков, как это сделано в выложенном примере. Естественно, игрок может выбирать любую букву. Не ставить же анимацию на каждую! Это уже чрезмерная работа, усилия по выполнению которой не стоят полученного результата. На помощь приходит «волшебный квадрат», и разрушение позитивного сюжета (анимация Выход) или строительство печальной композиции (анимация Вход) осуществляется сразу в один проход выделением всех элементов сюжета и добавлением им эффекта с триггером. Этот алгоритм относится к простым заданиям и описан в разделе 5.3.
  2. Вторая сложность – победный финал. Когда слово угадано полностью, хочется фанфар и фейерверков. Но мы заранее не знаем, какая из букв загаданного слова будет отгадана последней. Применяем технологию счетчика контроля количества (глава 9) такую же, как для игры «Найди все отличия», когда количество отличий не задано.
  3. Третья сложность – финал поражения. Здесь дело обстоит проще, так как есть точка привязки – разрушение последнего элемента сюжета. Надо создать финальную заставку и анимировать ее Входом, привязавшись также к «волшебному квадрату», который помогает обрабатывать неправильные буквы.
Альтернативы PowerPoint пока нет

В заключение хотелось бы подчеркнуть, что замены PowerPoint в смысле возможностей анимации нет. Аналоги — LibreOffice и OpenOffice — не поддерживают копирование анимации и замену рисунков с сохранением анимации. Анимация теряется, а делать каждый раз заново – неподъемный труд.

PowerPoint – не такая уж сложная программа. Изучение анимации — гораздо более простое дело, чем изучение программирования. Для реализации любых замыслов надо уметь работать с триггерами и применять прозрачные вспомогательные фигуры, которые мы со слушателями курсов назвали «волшебными квадратами» за их способность выручить в любой трудной ситуации. А я написала пошаговые алгоритмы для типовых заданий и издала книгу.

Как нарисовать виселицу буквами и знаками

Интересные задачи по Python для практики можно найти на нашем телеграм-канале «Библиотека задач по Python»

Обязательные условия

Проект, который вы будете создавать в рамках этого руководства, потребует от вас знакомства с программированием на Python. У вас должны быть базовые знания по следующим темам:

  • Создание приложений с графическим интерфейсом на базе PySimpleGUI
  • Работа с файлами и оператором with
  • Определение собственных классов и работа с объектно-ориентированным программированием
  • Использование циклов for , while и генераторов
  • Работа с условными операторами
  • Работа со строками, списками и множествами Python.

Статьи по теме

  • �� Самоучитель по Python для начинающих. Часть 15: Методы работы с файлами и файловой системой
  • �� Самоучитель по Python для начинающих. Часть 9: Особенности цикла for
  • �� Самоучитель по Python для начинающих. Часть 10: Условный цикл while
  • �� Самоучитель по Python для начинающих. Часть 18: Основы ООП – инкапсуляция и наследование

Шаг 1: Настройка проекта «Виселица»

Ваша игра « Виселица» будет реализована с помощью интерфейса PySimpleGUI, в котором пользователь сможет участвовать в процессе игры. Участник будет выбирать слово для отгадывания, а игра – обрабатывать вводимые пользователем данные и отображать все результаты с помощью графического интерфейса.

Вы можете скачать файлы и ресурсы для этого шага, использовав ссылку (в начале статьи) и перейдя в папку source_code_step_1/ .

Для работы над игрой вы будете использовать отдельный файл hangman.py . В этом файле вы создадите класс Hangman , который будет содержать код для создания графического интерфейса и логики игры. Этот файл также будет включать в себя главный цикл игры, который будет управлять ее действиями.

Итак, создайте директорию hangman/ , а затем – файл hangman.py с помощью вашего любимого редактора кода или IDE.

Вам также понадобится текстовый файл words.txt , в котором будет храниться список загаданных слов. Пример файла words.txt вы найдете в разделе « Выбор ключевого слова». Со вторым файлом у вас получится следующая структура каталогов для проекта виселицы:

Графический интерфейс вашей игры «Виселица»

Вы разместите рисунок повешенного человека в рамке слева от игрового окна. Затем вы расположите двадцать шесть кнопок в правой части окна. С помощью этих кнопок игрок будет отгадывать буквы. В нижней части над тремя кнопками будет располагаться слово, которое угадывается, а также кнопки для начала новой игры, перезапуска текущей игры и выхода из игры соответственно.

Внутри игры вы будете использовать свойства кнопок, чтобы показать, какие буквы может выбрать игрок. Например отключив кнопку при выборе буквы, вы не позволите игроку выбрать одну и ту же букву несколько раз. Отключенные кнопки также послужат визуальной подсказкой, какие буквы доступны для последующих угадываний.

Теперь, когда вы набросали графический интерфейс виселицы, пришло время приступить к созданию реального графического интерфейса с помощью библиотеки PySimpleGUI.

��➰ Создаем игру «Виселица» на Python. Часть 2. Графический интерфейс на PySimpleGUI

�� Подписывайтесь на еженедельную email-рассылку, посвященную последним открытиям и тенденциям в мире Python.

  • Новые возможности в последних версиях Python
  • Работа с базами данных и SQL в Python
  • Веб-разработка на Django и Flask
  • Машинное обучение и анализ данных с помощью Python
  • Автоматизация и работа с API на Python
  • Тестирование и отладка кода на Python
  • Задачи для новичков с решениями

Шаг 3: Код GUI-приложения для виселицы

Чтобы приступить к реализации проекта PySimpleGUI, например, игры в виселицу, вам понадобится создать каркас приложения. Затем нужно заняться созданием графического интерфейса виселицы, следуя схеме из предыдущего шага. И наконец, вы напишете код для изображения повешенного.

После завершения всех этапов этого шага вы получите готовый графический интерфейс виселицы. Однако этот графический интерфейс не будет обладать достаточной функциональностью, и, что более важно, он пока не позволит вам играть в игру.

Опять же, вы можете скачать исходный код для этого шага, использовав ранее полученный материал (папка source_code_step_3/ ).

Приложение PySimpleGUI, как правило, состоит из главного рабочего окна с определенным макетом или дизайном GUI и цикла событий. Чтобы создать игру « Виселица», откройте файл hangman.py в редакторе кода и добавьте в него следующий текст:

��➰ Создаем игру «Виселица» на Python. Часть 2. Графический интерфейс на PySimpleGUI

Отлично! У вашего окна появилась соответствующая надпись, и она позволяет вам нажать кнопку « Закрыть» в панели заголовка, чтобы завершить работу приложения. Теперь пришло время для создания графического интерфейса виселицы.

Шаг 4: Создание графического интерфейса виселицы

PySimpleGUI позволяет создавать графические интерфейсы в декларативном виде как данные, а не программно как код. В этом смысле библиотека похожа на другие инструменты для создания графических интерфейсов, такие как Qt Designer, который осуществляет генерацию графических интерфейсов в виде данных с использованием XML. Это отличная возможность, позволяющая отделить дизайн GUI от функциональности приложения.

В следующих разделах вы создадите подходящий макет для игры в виселицу. Вы также узнаете, как нарисовать строительные леса и повешенного человека.

Чтобы загрузить исходный код для этого шага – перейдите в папку source_code_step_4/ :

Создание графического интерфейса виселицы

В PySimpleGUI вы создаете графические интерфейсы с помощью вложенных списков. Каждый вложенный список представляет собой строку и может включать в себя несколько элементов управления. Поэтому первым шагом при преобразовании дизайна в программный код является разделение элементов GUI на строки или вложенные списки, содержащие определенные элементы PySimpleGUI.

Если вы посмотрите на свой дизайн GUI, то заметите, что вы можете сгруппировать компоненты GUI в три ряда. Выделение каждого ряда объектов в кружок, даст вам хорошую визуальную подсказку о том, где будет находиться каждый элемент:

��➰ Создаем игру «Виселица» на Python. Часть 2. Графический интерфейс на PySimpleGUI

Красными линиями выделены основные элементы пользовательского интерфейса, разбитые на ряды:

  • Первый ряд содержит область изображения повешенного человека и кнопки с буквами.
  • Во втором ряду находится отгадываемое слово.
  • В третьем ряду находятся кнопки « Новая игра», « Сброс» и « Выход».

Для отображения каждого ряда вы будете использовать отдельный вложенный список, содержащий соответствующие объекты управления PySimpleGUI для элементов в этом ряду.

Вы также можете обратить внимание на зеленые контуры, разделяющие буквенные кнопки на семь рядов. Вы сгруппируете эти кнопки во вложенные списки, которые вложите в первый ряд макета PySimpleGUI.

Макет PySimpleGUI – это обычный список Python. Поскольку глобальный макет GUI состоит из трех строк, вам нужно создать список с тремя вложенными блоками. Обновите класс Hangman , как показано в приведенном ниже коде:

Игра «Виселица»

Великолепно! Ваша игра « Виселица» приобретает законченную форму. Вы создали подходящий графический интерфейс для игры, который отлично смотрится! Однако графический интерфейс пока не реагирует на пользовательские действия. Вам предстоит исправить это, спроектировав логику игры и подключив ее к графическому интерфейсу.

Шаг 5: Разработка логики игры и подключение ее к графическому интерфейсу

До этого момента вы разрабатывали графический интерфейс виселицы с помощью PySimpleGUI. Теперь вам необходимо заняться написанием логики игры. Что еще более важно, вам нужно связать эту логику с графическим интерфейсом игры, чтобы она реагировала на действия пользователя.

Помимо прочего, вам потребуется написать код, который будет выполнять следующие действия:

  • Выбор подходящего слова
  • Отслеживание загаданного слова или букв
  • Запуск новой игры
  • Обработка ходов игрока
  • Определение момента окончания игры.

В следующих разделах вы реализуете необходимый код для управления этими задачами в своем проекте « Виселица». Начнем с того, что добавим соответствующий метод в класс Hangman . Этот метод будет определять процесс выбора загаданного слова для каждого матча в виселице.

Чтобы загрузить исходный код для этого шага – перейдите в папку source_code_step_5/ .

Выбор слова для отгадывания

Первый шаг в игре в виселицу – выбор слова-задания. Когда игрок выбирает слово для игры в виселицу, он использует одно слово из своего словарного запаса. Чтобы компьютер подобрал слово, ему необходимо иметь собственный словарь. Конечно, его словарный запас не должен быть таким же большим, как у человека.

Откройте файл words.txt . Этот файл будет содержать список, из которого игра будет выбирать подходящее слово. Полный исходный код этого шага, включая файл words.txt , вы можете найти в начале статьи.

После того как вы подготовили словарь, вам потребуется найти способ для выбора случайного слова из него. Предлагаем вам одно из возможных решений:

from random import choice # . class Hangman: # . def _select_word(self): with open("words.txt", mode="r", encoding="utf-8") as words: word_list = words.readlines() return choice(word_list).strip().upper() # . 

В этом фрагменте кода вы используете метод ._select_word() для выбора слова для отгадывания из файла words.txt . Вы используете оператор with для открытия файла и метод .readlines() для создания списка слов. Затем, с помощью метода choice() , выбираете случайное слово из списка.

Отслеживание загаданного слова

В реальной игре « Виселица» после того, как игрок выбрал слово, он должен отметить подчеркиванием каждую букву в слове. Эти подчеркивания подскажут отгадывающим игрокам, сколько букв в заданном слове. По мере того как отгадывающий игрок делает предположения, ведущий пишет правильные буквы над подчеркиваниями.

Чтобы сымитировать вышеописанный процесс в вашей игре в виселицу, вы будете использовать следующий вспомогательный метод:

# . class Hangman: # . def _build_guessed_word(self): current_letters = [] for letter in self._target_word: if letter in self._guessed_letters: current_letters.append(letter) else: current_letters.append("_") return " ".join(current_letters) # . 

Эта функция использует цикл for для заполнения списка current_letters . Цикл просматривает каждую букву в атрибуте ._target_word и определяет, содержится ли эта буква в ._guessed_letters . Если это так, то программа добавляет букву в current_letters . Если нет, то она добавляет знак подчеркивания _ к current_letters . После этого вы используете метод .join() для создания отображаемого слова, которое будет включать правильные буквы в соответствующих местах.

Обратите внимание, что вы еще не определили атрибуты ._target_word и ._guessed_letters . Вы сделаете это в следующем разделе.

Запуск или перезапуск игры

Каждый раз, когда вы запускаете игру « Виселица» или начинаете новый матч, вам нужно инициализировать несколько атрибутов, которые определяют состояние игры. Эти атрибуты представлены ниже:

  1. Заданное слово , ._target_word
  2. Угаданные буквы , ._guessed_letters
  3. Количество неправильных догадок , ._wrong_guesses
  4. Отображение загаданного слова , ._guessed_word

Для того чтобы определить, как вы начнете новую игру, вам необходимо инициализировать все эти атрибуты. Для этого используется метод ._new_game() :

# . class Hangman: # . def _new_game(self): self._target_word = self._select_word() self._restart_game() # . 

Внутри ._new_game() вы определяете атрибут ._target_word , который будет содержать выбранное слово для начала новой игры. Чтобы определить, какое слово использовать, вы обращаетесь к методу ._select_word() .

Затем вы используете метод ._restart_game() . В этом методе вы инициализируете остальные атрибуты, определяющие состояние игры. Обратите внимание, что наличие двух независимых методов облегчит поддержку кнопок « Новая игра» и « Перезапуск» соответственно. Вы сделаете это в следующем разделе.

Теперь напишите код для метода ._restart_game() :

# . class Hangman: # . def _restart_game(self): self._guessed_letters = set() self._wrong_guesses = 0 self._guessed_word = self._build_guessed_word() # Restart GUI self._canvas.erase() self._draw_scaffold() for letter in ascii_uppercase: self._window[f"-letter--"].update(disabled=False) self._window["-DISPLAY-WORD-"].update(self._guessed_word) # . 

Для отслеживания отгаданных букв вы будете использовать множество Python. Использование множества позволяет оперативно проверять, отгадал ли игрок заданную букву, используя тесты принадлежности с помощью оператора in .

Атрибут ._wrong_guesses будет содержать количество неправильных догадок, сделанных игроком. Его первоначальное значение равно 0. Далее вы используете функцию ._build_guessed_word() , определяющую заданное слово. Обратите внимание, что перезапуск игры не подразумевает выбора нового слова для отгадывания.

Последние строки этого метода напрямую связаны с графическим интерфейсом игры и требуют более подробного объяснения.

Каждый раз, когда вы перезапускаете игру, вам необходимо сбросить рисунок повешенного человека. Для этого вы в первую очередь обращаетесь к методу .erase() объекта Graph , который используется в качестве холста. Затем вы перерисовываете строительные леса. После этих изменений область рисования готова к запуску новой или перезапуску игры.

Далее вы перебираете список ASCII и активируете все кнопки с буквами в графическом интерфейсе виселицы. Почему это необходимо сделать? Помните, как в реальной игре в виселицу вам нужно отслеживать все отгаданные буквы?

Так вот, в вашей графической реализации виселицы вы будете отслеживать количество угаданных букв, отключая их после того, как игрок нажмет на соответствующую кнопку.

Чтобы завершить модернизацию графического интерфейса игры, вы обновляете загаданное слово, чтобы оно соответствовало последнему ходу игрока. В следующем разделе вы займетесь обработкой вводимых игроком данных.

Обработка вводимых игроком данных

В рамках реализации игры « Виселица», ход совершается, когда угадывающий игрок нажимает на кнопку с буквой. Клик – это действие, поэтому вы можете перехватить его и обработать, используя возможности PySimpleGUI. Для этого вы используете два метода, .process_event() и ._play() .

Метод .process_event() – это универсальный метод, который вы будете использовать для обработки всех соответствующих пользовательских взаимодействий или сообщений. В свою очередь, ._play() будет обрабатывать ходы игрока, которые представляют собой нажатие на кнопку с буквой.

Ниже приведен код с использованием метода .process_event() :

# . class Hangman: # . def read_event(self): # . def process_event(self, event): if event[:8] == "-letter-": self._play(letter=event[8]) elif event == "-RESTART-": self._restart_game() elif event == "-NEW-": self._new_game() # . 

В .process_event() аргумент event содержит только идентификатор действия, который вы задали через аргумент key , когда назначали кнопки в макете. Условный оператор проверяет, является ли текущее действие щелчком по кнопке с буквой.

Изначально вы задали для клавиши letters значение f» -letter—» . В условном операторе проверяется, совпадают ли первые восемь символов в идентификаторе текущего действия со строкой » -letter- » . Таким образом можно определить, что текущее действие – это нажатие на кнопку с буквой. Если это так, тогда вы обращаетесь к методу ._play() с текущей буквой в качестве аргумента.

Условия elif обрабатывают действия » -RESTART- » и » -NEW- » соответственно. Действие » -RESTART- » осуществляется, когда игрок нажимает кнопку « Перезапуск», а действие » -NEW- » – когда игрок нажимает кнопку « Новая игра». В любом случае вы вызываете соответствующий метод.

Теперь необходимо сформулировать метод ._play() :

# . class Hangman: # . def _restart_game(self): # . def _play(self, letter): if letter not in self._target_word: self._wrong_guesses += 1 self._guessed_letters.add(letter) self._guessed_word = self._build_guessed_word() # Update GUI self._window[f"-letter--"].update(disabled=True) self._window["-DISPLAY-WORD-"].update(self._guessed_word) self._draw_hanged_man() # . 

В методе ._play() прежде всего проверяется, нет ли угаданной буквы в заданном слове. В этом случае счетчик неправильных догадок увеличивается на единицу. Если текущая буква есть в загаданном слове, то она добавляется в список угаданных букв, что позволяет вести их учет. Затем вы обновляете загаданное слово, вызывая ._build_guessed_word() .

Следующие три строки позаботятся об обновлении графического интерфейса игры. Во-первых, вы отключаете кнопку нажатия на букву. Это действие гарантирует, что игрок не сможет повторно нажать на кнопку с буквой. Затем вы обновляете загаданное слово и, наконец, обновляете изображение повешенного.

После того как вы написали код для получения и обработки вводимых игроком данных, вам осталось определить, в какой момент игра будет окончена.

Определение завершения игры

Игры обычно заканчиваются по условию, заданному ходами игрока. Возможно, игрок наконец-то достиг поставленной цели, или же он не справился с каким-то заданием и проиграл.

Обычно « Виселица» заканчивается, когда происходит одно из двух событий:

  • Игрок допустил шесть ошибочных догадок, что свидетельствует о его проигрыше.
  • Игрок правильно отгадал слово, и, соответственно, победил.

У вас имеются два условия для проверки, поэтому вы можете включить их в отдельный метод. Вы назовете метод .is_over() , и это будет предикатный метод, возвращающий True или False .

Ниже представлена его реализация:

# . class Hangman: # . def process_event(self, event): # . def is_over(self): return any( [ self._wrong_guesses == MAX_WRONG_GUESSES, set(self._target_word)  

Высчитать количество неправильных предположений очень просто. У вас уже есть константа MAX_WRONG_GUESSES . Поэтому вам остается только проверить, равно ли количество неправильных догадок этому значению.

В отличие от этой задачи, проверка того, правильно ли игрок угадал слово, может потребовать небольшого комментария. Если вы играете в виселицу на доске, то ведущий игрок может посмотреть на слово целиком, чтобы убедиться, что оно верно отгадано. Однако ваш графический интерфейс не может этого сделать. Он должен рассматривать каждую букву в отдельности.

Именно здесь на помощь приходит интегрированный класс множеств. Он преобразовывает любую итерируемую переменную в объект группы. Поскольку каждый элемент в массиве данных уникален, он создает множество, состоящее из букв, образующих загаданное слово, за исключением повторов.

Встроенная функция any() возвращает True , если хотя бы одно из перечисленных условий истинно. В противном случае она возвращает False .

Результат выполнения функции .is_over() зависит от хода игрока. Поэтому имеет смысл использовать этот метод для управления циклом событий игры.

Обновление цикла событий и запуск игры

До этого момента вы проделали большую работу по написанию кода. Вы реализовали логику виселицы и подключили ее к графическому интерфейсу на основе PySimpleGUI. Однако вам необходимо реализовать весь этот код в реальной игре. Вы сделаете это в общем игровом цикле.

Обновите главный цикл, как показано в приведенном ниже коде:

# . if __name__ == "__main__": game = Hangman() # Event loop while not game.is_over(): event_id = game.read_event() if event_id in : break game.process_event(event_id) game.close() 

В новой версии цикла событий вашей игры вы используете .is_over() для управления им. Теперь цикл будет выполняться до тех пор, пока не будет соблюдено одно из условий завершения игры. Внутри цикла вы включаете функцию .process_event() с идентификатором текущего действия в качестве аргумента.

Вы можете заметить, что теперь кнопки с буквами, изображение повешенного человека и загаданное слово наконец-то заработали. Вы даже можете сыграть свой первый матч. Вы также увидите, что кнопки « Новая игра» и « Перезапуск» функционируют.

Обратите внимание, что кнопки с буквами не отличаются от остального графического интерфейса по цвету фона. Однако, когда вы наводите на них курсор, они автоматически подсвечиваются, сообщая о том, что вы можете на них нажать. Если вы уже щелкнули по какой-либо буквенной кнопке, то она становится неактивной, и при наведении на нее указателя мыши – цвет больше не меняется.

Шаг 6: Обработка результатов игры

На этом шаге у вас уже имеется функциональная игра « Виселица». В ней можно отгадывать заданное слово, нажимая на кнопки с буквами. Кнопки « Новая игра» и « Перезапуск» также работают. Однако игра автоматически закрывается, когда вы выигрываете или проигрываете текущий матч. Это не очень приятно, не так ли?

Вы должны дать своей игре « Виселица» возможность проверить условия выигрыша и сообщить игроку о конечном результате. Также было бы неплохо дать игроку возможность сыграть несколько раундов, показывая при этом суммарные результаты. Для начала вы определите победителя и дадите игроку возможность сыграть еще раз.

Опять же, вы можете скачать исходный код для этого шага и перейти в папку source_code_step_6/ .

Определение победителя и повторная игра

В вашей игре « Виселица» побеждает игрок, отгадавший заданное слово до того, как будет сделано шесть неверных предположений. В этом случае вы хотите продемонстрировать поздравительное сообщение, свидетельствующее о победе. В противном случае вы хотите проинформировать игрока о том, что он проиграл матч.

Ниже приведен метод .check_winner() , который позволяет проверить условие победы и вызвать всплывающее окно с соответствующей информацией для игрока:

# . class Hangman: # . def is_over(self): # . def check_winner(self): if self._wrong_guesses < MAX_WRONG_GUESSES: answer = sg.PopupYesNo( "You've won! Congratulations!\n" "Another round?", title="Winner!", ) else: answer = sg.PopupYesNo( f"You've lost! The word was ''.\n" "Another round?", title="Sorry!", ) self.quit = answer == "No" if not self.quit: self._new_game() # . 

В функции .check_winner() вы проверяете, не превышает ли количество неверных предположений максимальное число допустимого значения – 6. Помните, что это число соответствует количеству элементов на изображении повешенного человека. Если условие истинно, то игрок выиграл, и вы выводите поздравительное сообщение во всплывающем окне.

Если условие ложно, то вы отображаете всплывающее окно, сообщающее игроку, что он проиграл. В нем также содержится информация о загаданном слове.

Обратите внимание, что оба всплывающих окна также предлагают отгадавшему игроку сыграть еще один раунд. После выполнения условия вы присваиваете атрибуту .quit логическое значение, которое зависит от ответа игрока о готовности сыграть еще один раунд.

Если значение .quit равно False , то вы обращаетесь к ._new_game() , чтобы сбросить загаданное слово и начать новую игру в виселицу.

Чтобы этот код заработал, вам необходимо добавить атрибут .quit в инициализатор класса Hangman :

# . class Hangman: def __init__(self): # . self._new_game() self.quit = False # . 

Эта новая строка кода добавляет атрибут .quit в Hangman . По умолчанию атрибут имеет значение False . Теперь, когда все эти изменения внесены, можно обновить цикл игры. Чтобы управлять множеством раундов, вы заключите цикл событий во внешний цикл, связанный с атрибутом .quit :

# . if __name__ == "__main__": game = Hangman() # Rounds while not game.quit: # Event loop while not game.is_over(): event_id = game.read_event() if event_id in : game.quit = True break game.process_event(event_id) if not game.quit: game.check_winner() game.close() 

В этом обновленном коде вы заключаете цикл событий во внешний цикл, который позаботится об обработке нескольких раундов игры в виселицу. Этот внешний цикл использует атрибут .quit в процессе выполнения условий. Цикл будет повторяться до тех пор, пока игрок не закроет окно игры или не нажмет кнопку « Выход». В этот момент атрибут .quit станет True , а условие цикла – false .

Две предпоследние строки включают в себя условный оператор, который проверяет, вышел ли игрок из игры. Если это так, тогда вы обращаетесь к методу .check_winner() .

Когда вы угадываете заданное слово, игра выводит сообщение о вашей победе и приглашает сыграть еще один матч. Если вы нажмете кнопку « Да», то игра выберет другое подходящее слово, и вы сможете начать новый раунд. Если вы нажмете кнопку « Нет», то игра завершится. Попробуйте!

Ведение счета и результаты

Отлично, теперь вы знаете, кто победил в одиночной игре! Но что, если ваш пользователь захочет помериться силами с компьютером в игре « Лучший из трех»? Ведение счета игрока на протяжении нескольких раундов – еще одна интересная функция в игре « Виселица». Вы можете отслеживать проведенные и выигранные партии. Итак, вам потребуется добавить два новых атрибута:

# . class Hangman: def __init__(self): # . self.quit = False self._played_games = 0 self._won_games = 0 # . 

Эти два атрибута позволяют отслеживать количество сыгранных игр, а также число побед в них. Теперь вы можете включить необходимый код для поддержки этой новой функции.

Для этого вы можете отредактировать метод .check_winner() , как показано в приведенном ниже фрагменте кода:

# . class Hangman: # . def check_winner(self): self._played_games += 1 if self._wrong_guesses < MAX_WRONG_GUESSES: self._won_games += 1 answer = sg.PopupYesNo( "You've won! Congratulations!\n" f"That's out of !\n" "Another round?", title="Winner!", ) else: answer = sg.PopupYesNo( f"You've lost! The word was ''.\n" f"That's out of !\n" "Another round?", title="Sorry!", ) self.quit = answer == "No" if not self.quit: self._new_game() # . 

В первой строке .check_winner() вы увеличиваете количество сыгранных игр с помощью добавочного присваивания. В условии if вы увеличиваете количество выигрышей. Эти два счетчика позволяют отслеживать необходимую информацию, которую затем добавляют в сообщение, отображаемое в каждом из всплывающих окон.

Ваша игра « Виселица» готова к чемпионату! Она позволяет проводить несколько раундов, а также ведет подсчет очков и информирует о ваших результатах. Попробуйте, а затем пригласите друзей!

Получите свой код: Нажмите здесь, чтобы загрузить бесплатный исходный код Python для вашей игры в виселицу PySimpleGUI.

Заключение

Создание игры « Виселица» с помощью Python и PySimpleGUI – это отличный способ развития навыков программирования, изучения новых техник и знакомства с миром компьютерных игр на базе GUI. Написав игру на Python, вы решили несколько задач по кодированию и дизайну, включая создание подходящего графического интерфейса, получение и обработку пользовательских действий, а также обновление интерфейса игры в зависимости от ее состояния.

В этом руководстве вы узнали, как:

  • Использовать PySimpleGUI при создании графического интерфейса пользователя для игры в виселицу
  • Реализовать логику и правила игры в виселицу на Python
  • Связывать логику игры и компоненты графического интерфейса пользователя
  • Оценивать результаты игры и предлагать пользователям дополнительные опции

Теперь у вас есть все необходимые инструменты и навыки, благодаря которым вы можете дополнять и совершенствовать свою игру « Виселица». Вы также можете заняться созданием других подобных игр.

Следующие шаги

Теперь, когда вы закончили работу над своей игрой « Виселица», вы можете сделать еще один шаг вперед, реализовав несколько дополнительных функций. Самостоятельное добавление новых элементов поможет вам освоить ряд интересных тем.

Предлагаем вам несколько идей:

  • Использование специализированных списков слов: вы можете добавить в игру различные списки слов, чтобы иметь возможность выбрать наиболее подходящий в зависимости от аудитории и ее предпочтений.
  • Настройка уровней сложности: вы можете классифицировать загаданные слова по уровню сложности, основываясь на длине слова и его распространенности, и так далее.
  • Использование иностранных слов: можно составить списки слов на разных языках, чтобы игроки могли потренировать свои лингвистические навыки.
  • Добавление звуковых эффектов: вы можете добавить в игру пользовательские звуковые эффекты, чтобы акцентировать внимание на наиболее важных действиях.
  • Настройка цвета фона кнопок с буквами: вы можете установить другой цвет фона для тех кнопок с буквами, на которые игрок уже нажимал. Такое решение обеспечит визуальную подсказку для игрока и улучшит его общее представление об игре.

Чем вы займетесь дальше? Поделитесь своими идеями в комментариях!

Статьи по теме

  • ���� Создаем игру «Жизнь» Джона Конвея на Python
  • �� Самоучитель по Python для начинающих. Часть 21: Основы разработки игр на Pygame
  • �� Самоучитель по Python для начинающих. Часть 20: Графический интерфейс на Tkinter

Источники

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *