Статьи

Начало работы с Ruby, III: числа и логика

В последней части этой серии мы рассмотрели строки и их методы, а также сохранили информацию в качестве переменных. Мы также написали программу Greeter и программу Madlibs, создавая их веб-версии с использованием Sinatra. В этом посте основное внимание уделяется тому, как использовать числа в Ruby и создавать логические операторы.

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

Время для некоторых сумм!

 4 + 5 => 9 

4 и 5 оба являются объектами, а + на самом деле является методом. В предыдущем посте мы видели, как вызывать метод с использованием точечного синтаксиса, и вы можете сделать то же самое с методом + :

 4.+(5) 

Это пример добавления аргументов в метод. 4 — объект, вызывающий метод + а 5 — аргумент. Ruby позволяет нам писать это более естественным образом (например, писать арифметику). Это известно как синтаксический сахар , поэтому 4 + 5 считается эквивалентным 4.+(5) .

Мы можем сделать много различной арифметики подобным образом:

 10 - 4 => 6 4 * 8 => 32 9 / 2 => 4 

… Подожди! Эта последняя сумма была неверной. Это потому, что 9 и 2 оба являются целыми числами. Это означает, что решение 9/2 даст вам только целую часть ответа. Чтобы получить правильный ответ, нам нужно использовать другой тип числа, называемый Float (потому что они используют десятичные числа с плавающей запятой). Чтобы использовать числа с плавающей точкой вместо целых чисел, просто запишите 9 как 9.0 (это называется литералом Float)

 > 9.0/2 => 4.5 

Так-то лучше!

Ruby дает нам методы, чтобы узнать, является ли число нечетным или четным:

 > 4.odd? => false > 5.odd? => true 

В последнем посте мы узнали о «методах взрыва». odd? и even? методы являются примерами логических методов . Это методы, которые только возвращают результат true или false . Они обычно имеют знак вопроса (‘?’) В конце метода.

Ruby также может делать довольно крутые математические вещи, например, находить наибольший общий делитель двух чисел, используя метод gcd Один номер вызывает метод (12 в примере ниже), а другой номер — аргумент метода (20 в примере ниже):

 > 12.gcd(20) => 20 

Существует также метод lcm который находит наименьшее общее кратное двух чисел:

 > 15.lcm(20) => 60 

Один из моих любимых методов — метод times , показанный в следующем примере:

 > 5.times do > puts "Hello!" > end Hello! Hello! Hello! Hello! Hello! 

Мне нравится, как он инкапсулирует читаемость языка программирования Ruby. Он действительно делает то, что говорит на банке, и читает почти как английское предложение. Кстати, фрагмент кода между операторами do и end называется блоком, и мы собираемся рассказать о них гораздо больше в будущих публикациях.

Последний метод Integer который мы рассмотрим, — это метод to_s , который обозначает «to string». Он принимает целое число и преобразует его в строковое представление этого целого числа, например:

 > 7.to_s => "7" 

Это позволяет вам рассматривать число как строку. Существует также эквивалентный метод для строк, называемый to_i который превращает строку в целое число:

 "42".to_i => 42 

Вы должны быть осторожны с этим, поскольку строка должна иметь несколько чисел в начале, иначе она вернет 0 (вы можете увидеть больше здесь ).

Генерация случайных чисел

Часто полезно генерировать случайное число при программировании. Это легко сделать в Ruby, используя метод rand . Это сгенерирует число с плавающей запятой от 0 до 1,0, например, так:

 > rand => 0.29635454177765397 

Если вы предоставите целочисленный аргумент, он сгенерирует случайное целое число от 0 до, но не включая аргумент. Например:

 > rand(6) => 2 

Приведенный выше код сгенерирует случайное число от 0 до 5. Мы можем использовать это (и немного арифметики, которую мы изучили ранее, чтобы подражать броску кубика:

 > rand(5) + 1 => 4 

Посмотрите этот очень подробный пост Роберта Куалла о случайных связях и Руби для получения дополнительной информации.

логика

Мы можем создавать логические операторы в Ruby, используя оператор if и then . Например, мы могли бы сыграть в игру, пытаясь бросить 6 на кубике:

 number = rand(5) + 1 if number == 6 then puts "Congratulations, you rolled a six!" end 

Большую часть этого довольно легко понять, но есть несколько ошибок. Прежде всего, обратите внимание на разницу между = и == . В первом случае мы используем = для присваивания , то есть установки переменной, в этом случае «число», равное значению, случайное число от 1 до 6. Во втором случае мы используем == для проверки равенства , В этом примере мы проверяем, равно ли значение числа 6. Будьте осторожны, чтобы не перепутать их, потому что пишите это:

 if number = 6 then puts "Congratulations, you rolled a six!" end 

фактически устанавливает значение числа в 6 и, следовательно, всегда будет истинным!

Есть также else заявление:

 number = rand(5) + 1 if number.odd? puts "You rolled an odd number" else puts "You rolled an even number" end 

Обратите внимание, что вам на самом деле не нужно использовать оператор then . Мы также можем вкладывать много утверждений, используя выражение elsif (не правописание!):

 number = rand(5) + 1 if number == 1 puts "You rolled a 1" elsif number == 2 puts "You rolled a 2" elsif number == 3 puts "You rolled a 3" elsif number == 4 puts "You rolled a 4" elsif number == 5 puts "You rolled a 5" else puts "You rolled a 6" end 

Программа «Угадай мой номер»

Теперь, когда мы немного узнали о том, как работают числа, мы напишем короткую программу, которая предлагает пользователю угадать произвольно выбранное целое число от 1 до 100. Сохраните следующий код в файле под названием «угадай мое число». .rb ‘:

 number = rand(100) + 1 puts "I'm thinking of a number between 1 and 100, try and guess what it is" guess = gets.to_i attempts = 1 until guess == number do if guess < number then puts "Too small, try again" elsif guess > number then puts "Too big, try again" end guess = gets.to_i attempts += 1 end puts "Well done, you guessed my number in #{attempts} attempt#{'s' if attempts > 1}!" 

Сначала мы устанавливаем переменную с именем number , которая является случайным числом от 1 до 100, которое необходимо угадать. Мы используем метод rand с аргументом 100, а затем добавляем 1, чтобы установить это.

После этого метод puts используется для печати строки, объясняющей, что должен делать игрок.
Затем метод gets получает от игрока предположение, которое хранится в переменной с именем guess . Любой ввод от пользователя сохраняется в виде строки (даже если вы вводите число), поэтому нам нужно использовать метод to_i чтобы гарантировать, что значение рассматривается как целое число.
Затем установите количество попыток в 1, используя переменную attempts . Это будет использоваться для отслеживания количества попыток пользователя, прежде чем правильно угадать.
Затем, есть утверждение, until guess == number do . Это хороший кусочек Ruby, который говорит: пока догадка не будет равна числу, сделайте следующее. Это пример цикла, который мы рассмотрим более подробно в следующей части серии.

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

Мы используем операторы if и elsif чтобы проверить, меньше или больше предположение, чем число, а затем даем соответствующую обратную связь. После этого сделайте еще одно предположение и увеличьте количество попыток на 1. Это делается с помощью оператора attempts += 1 , что является сокращением для attempts = attempts + 1 записи attempts = attempts + 1 .

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

Угадай мой номер в Интернете

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

Один из способов обойти это — использовать сеансы. Это легко сделать в Синатре — вам просто нужно включить их. Создайте файл с именем «веб- угадать the_number.rb» и добавьте следующие строки:

 require 'sinatra' enable :sessions 

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

Теперь, когда мы хотим настроить игру, мы начнем с создания обработчика маршрута для корневого URL-адреса (находится по адресу http: // localhost: 4567 ), когда пользователь запрашивает веб-страницу.

 get '/' do @message = "I'm thinking of a number between 1 and 100, try and guess what it is" session[:number] = rand(100) + 1 session[:attempts] = 0 erb :guess end 

Прежде всего, установите переменную экземпляра с именем @message . Переменные экземпляра всегда начинаются с символа @ и они доступны в представлении, связанном с обработчиком маршрута. В конце обработчика маршрута мы вызываем guess используя ERB. По нашему мнению, мы сможем ссылаться на переменную @message . Кроме того, мы устанавливаем переменные количества и попыток в этом обработчике маршрута.

Как упоминалось ранее, мы используем для этого сеансы, иначе информация будет потеряна после каждого запроса. Это делается с помощью хеша для хранения информации, поэтому session[:number] содержит значение количества, а session[:attempts] содержит значение количества попыток.

Нам нужен некоторый HTML-код, который мы напишем с использованием ERB, следующий код идет в конце файла:

 __END__ @@guess <!doctype html> <html> <header> <title>Guess the Number</title> </header> <body> <p><%= @message %></p> <form method="POST" action="/"> <input name="number"> <input type="submit" value="Guess"> </form> </body> </html> 

Это базовая веб-страница, которая содержит форму для отправки предположения. Форма будет опубликована с использованием метода HTTP POST, и нам также необходимо указать маршрут, где она будет опубликована. В этом случае мы делаем то, что называется обратной передачей, когда мы используем тот же URL-адрес, на котором находится форма (в данном случае это корень сайта ‘/’). Обратите внимание, что атрибут name является number как нам понадобится это, чтобы получить его значение при публикации формы.

Нам нужно создать обработчик маршрута, когда это произойдет. Поскольку форма POSTed, мы будем использовать метод post для нашего обработчика маршрута с маршрутом, который был указан в атрибуте действия формы. Поместите следующий код после другого обработчика маршрута (но перед кодом ERB):

 post '/' do number = session[:number] guess = params[:number].to_i session[:attempts] += 1 redirect to('/success') if guess == number if guess < number then @message = "Too small, try again" elsif guess > number then @message = "Too big, try again" end erb :guess end 

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

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

Если пользователь не перенаправлен, тогда его предположение должно быть неверным, поэтому мы используем некоторую логику if и elsif чтобы проверить, является ли предположение слишком большим или слишком маленьким, и обновим @message экземпляра @message соответствующим сообщением. Мы заканчиваем, снова отображая представление догадок в ERB, чтобы пользователь мог представить другую догадку.

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

Все, что осталось сделать, это создать обработчик маршрута успеха. Это идет после последнего обработчика маршрута:

 get '/success' do attempts = session[:attempts] "Well done, you guessed my number in #{attempts} attempt#{'s' if attempts > 1}!" end 

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

ruby web_guess_the_number играть в игру, введя ruby web_guess_the_number в терминале, чтобы запустить сервер, а затем ruby web_guess_the_number на http: // localhost: 4567 в своем браузере.

Это все люди

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