Rubyrush: Пишу консольную игру «Южное Бутово»

Ruby для новичков [Rubyrush]

Сегодня я для себя открыл команду gets — получение данных от пользователя через ввод данных в консоли.

До этого момента я не вводил данные, а генерировал их методами, или явно задавал через присваивание значений пременным.

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

В видео уроке ребята рассказывают о том, как используя условные операторы и команду gets писать не сложные текстовые игры, похожие на интерактивные истории. Приступим!

Gets и puts — два метода дополняющие друг друга

Ранее я уже изучал и часто использовал метод вывода данных — puts. Ни одна программа не обходилась без него. Пришло время добавить новую фичу! Метод gets действует ровно наоборот — он сохраняет введённые пользователем данные и дальше мы можем делать с ними все что угодно.

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

puts "Привет тебе, человек! Скажи своё имя, пожалуйста."

name = gets

puts "Приятно познакомиться, " + name

В этой простой программе мы работаем с оператором вывода и ввода. введённые данные мы сохраняем в переменную.

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

Но как только я взялся за тестирование этой программы у меня появилось несколько проблем и это довольно интересно было решать.

Проблема с отображением кириллических символов (если ввели имя на русском языке)

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

Rubyrush: Пишу консольную игру «Южное Бутово»
Пример некорректного отображения русского имени в терминале.

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

# encoding: utf-8

Но это меня не избавило от проблемы. Пришлось искать в интернетах решение. И я его нашёл!

При написании программы на ruby, которая берет ввод пользователя из консоли, иногда возникают проблемы. Даже если файл сохранен в кодировке UTF-8, русские символы программа не выводит.

Решение проблемы с отображением русских символов

Ультимативное решение — вставить в начале файла код:

# XXX/ Этот код необходим только при использовании русских букв на Windows
if (Gem.win_platform?)
  Encoding.default_external = Encoding.find(Encoding.locale_charmap)
  Encoding.default_internal = __ENCODING__

  [STDIN, STDOUT].each do |io|
    io.set_encoding(Encoding.default_external, Encoding.default_internal)
  end
end
# /XXX

Проверил на своей программе и это работает! Теперь что бы я не вводил — оно отображается правильно.

Rubyrush: Пишу консольную игру «Южное Бутово»
Демонстрация решения с кодировкой при вводе кириллических символов.

Проблема с переносом строки при вызове gets

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

Rubyrush: Пишу консольную игру «Южное Бутово»

Это связанно с тем, что при вводе и отправке данных используется клавиша enter. При отправке автоматически в конце ставится перенос на новую строку.

Как я решал эту проблему с нежелательным

Для начала я вспомнил про интерполяцию и переписал программу на вот такой вариант:

Rubyrush: Пишу консольную игру «Южное Бутово»
Демонстрация применения интерполяции в программе на Ruby.

Но это конечно же не помогло и я вспомнил про книжку ,которую читаю в поездках по городу — Head First. Изучаем Ruby от Джея Макгавена. В ней я читал про метод chomp.

Метод chomp обладает более узкой специализацией, чем методы
print, puts и gets: он доступен только для объектов строк. Это
означает, что строка, на которую ссылается переменная input,
должна быть указана как получатель метода chomp. К переменной
input необходимо применить оператор «точка».

В итоге я добавил этот метод в маркер с подстановкой значения переменной в строку и смог избавиться от нежелательного переноса на новую строку:

Rubyrush: Пишу консольную игру «Южное Бутово»
Пример решения — как удалить нежелательный перенос на след строку.

В итоге код моей программы стал вот таким:

# XXX/ Этот код необходим только при использовании русских букв на Windows
if (Gem.win_platform?)
  Encoding.default_external = Encoding.find(Encoding.locale_charmap)
  Encoding.default_internal = __ENCODING__

  [STDIN, STDOUT].each do |io|
    io.set_encoding(Encoding.default_external, Encoding.default_internal)
  end
end
# /XXX

puts "Привет тебе, человек! Скажи своё имя, пожалуйста."
name = gets
puts "Приятно познакомиться, #{name.chomp} :)"

Проходим урок дальше

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

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

Как декодировать введённые данные в UTF-8

Ребята в уроке демонстрируют точечное решение. Для решения проблемы достаточно при сохранении данных в переменную добавить специальный метод encode и в аргументе передать ему желаемый формат кодировки:

puts "Привет тебе, человек! Скажи своё имя, пожалуйста."
name = gets.encode(UTF-8)
puts "Приятно познакомиться, #{name} :)"

Как избавиться от нежелательного переноса строки

Аналогичное решение. Тоже использую метод chomp, вот только в отличии от меня, они внятно и доходчиво объясняют как работает этот метод — он как бы отрезает перенос строки от введённых данных.

puts "Привет тебе, человек! Скажи своё имя, пожалуйста."
name = gets.encode(UTF-8)
puts "Приятно познакомиться, #{name.chomp} :)"

Как правильно задавать названия переменным

По ходу дела я понял, что задаю не совсем корректные имена для переменных, используя стиль из JS (СинийСлон). Там я писал слова из которых состояло имя переменной слитно и каждое новое слово начиналось с большой буквы.

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

Про саму игру из урока

Ребята наглядно продемонстрировали что текстовая игра на Ruby это очень просто и интересно. Я когда смотре — у меня столько идей в голове мелькало, Круть! Я не буду пошагово расписывать что и как они делали, а просто пройдусь по основным принципам написания программы. В далее я напишу свою игру используя полученные знания из этого урока.

Для написания программы мы используем следующий алгоритм действий:

  1. Выводим на экран вводное описание, которое описывает время и место происходящего. Как бы погружаем игрока в историю.
  2. Затем задаем вопрос и предлагаем сделать выбор из предложенных вариантов ответа. Все варианты прономерованы и для выбора достаточно ввести понравившийся номер ответа.
  3. Затем, в зависимости от выбранного варианта действий, мы выводим на экран описание последствий этого решения. тут обычно несколько вариантов (ветвление) и если игрок принимает не верное решение игра заканчивается. А если решение было верным, игра раскрывает дальнейший сюжет и предлагает сделать очередной выбор действий.

Что используем при написании игры

  • Метод puts — вывод информации на экран
  • Метод gets — ввод информации в консоли
  • Переменные — для сохранения информации, которую вводит пользователь
  • if-else — условный оператор, позволяющий программировать последствия в зависимости от выбранных ответов игрока.
  • Метод abort — прекращает работу программы и выводит завершающее сообщение на экран.

Дополнительные методы

  • encode — Явное указание кодировки, для входящих данных в программе.
  • chomp — обрезание нежелательного пробела в конце сохранённых в переменную входящих данных.

Пишем свой собственный квест

В итоге я на столько увлекся написанием игры что погрузился в процесс на ТРИ дня. за это время я набил несколько шишек и все это решил описать в отдельной статье. Почитайте её тут.

Rubyrush: Пишу консольную игру «Южное Бутово»

Моя первая игра на Ruby

Как я решился на написание текстовой игры

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

Так как в рамках курса была продемонстрирована не сложная и очень жизненная текстовая игра про путешествие по Бутово, то и я решил попробовать сделать что то аналогичное…

Видео с разбором урока и игры

Юрий Ронин