Rubyrush: Игра Угадайка и повтор пройденного материала

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

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

Игра «Угадайка»

Задание на написание игры

Мне нужно написать игру, которая загадывает случайное число от 0 до 15 включительно, а затем предлагает его угадать.

Для угадывания даётся ТРИ попытки.

Если игрок не угадывает — ему даётся подсказка:

  • программа отвечает «тепло» если введенное число отличается от загаданного на 2 или меньше.
  • программа отвечает «холодно» если введенное число отличается от загаданного на 3 и больше.

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

Если игрок угадывает число за ТРИ попытки — игра поздравляет пользователя с победой и завершается.

Если не угадывает — игра сообщает какое число была загадано.

Дополнительное задание

В качестве развлечения найдите алгоритм гарантированно угадать число за 3 попытки.

Подсказки по написанию игры

По заданию игра должна загадывать число от 0 до 15 включительно.

Для реализации мы объявляем переменную number в которую сохраняем диапазон чисел от 0 до 15 включительно. Random numbers — метод для получения случайного числа. В аргументе передаётся ЦЕЛОЕ ЧИСЛО. Так как нам нужно получать числа от 0 до 15 включительно — передаём в аргумент число 16. В итоге программа выглядит вот так:

number = rand(16)

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

Для реализации мне достаточно просто вывести на экране текст.

Теперь программа выглядит вот так:

number = rand(16)

puts "Приветствуем тебя в игре \"Угадайка\"! ",
"Загадано число от 0 до 15 включительно.",
"У тебя есть три попытки отгадать его."

Дальше нужно предложить ввести число.
Для этого мы я использую метод gets.
А для того что бы можно было удобно работать со входящими данными, я сохраню число, которое ввёл игрок в переменную guess_number.
Зная что при вводе данных сохраняется ненужный перенос строки, а так же объект имеет класс трока, я преобразую объект в число и обрезаю ненужный перенос строки.

Теперь программа выглядит вот так:

number = rand(16)

puts "Приветствуем тебя в игре \"Угадайка\"! ",
"Загадано число от 0 до 15 включительно.",
"У тебя есть три попытки отгадать его."

puts "Какое число загадано?"
guess_number = gets.chomp.to_i

Теперь у нас в программе сохранено два числа: number — случайное число от 0 до 15 включительно и guess_number — число, которое загадал игрок.

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

Для реализации пишу конструкцию if else. В которой прописываю условия — если число игрока совпадает с загаданным числом — победа и завершение игры. А если не совпадает — сравниваю число игрока с загаданным числом. Если число меньше загаданного — даю подсказку, что нужно загадать число побольше. В остальных случаях число будет больше, поэтому просто говорим что нужно число поменьше. Теперь моя программа выглядит вот так:

number = rand(16)

# Для тестирования
puts number

puts "Приветствуем тебя в игре \"Угадайка\"! ",
"Загадано число от 0 до 15 включительно.",
"У тебя есть три попытки отгадать его."

guess_number = gets.chomp.to_i

if guess_number == number
  puts "Ты угадал число! Молодец!",
  "Игра пройдена!"
  exit
else
  # сравниваем число игрока с загаданным числом на больше или меньше и даём подсказку №1
  if guess_number < number
    puts "Нужно число побольше ;)"
  else
    puts "Назови число поменьше ;)"
    end
end

Для того что бы завершить игру и выйти из программы я использую метод exit.

Важно учитывать что для корректной работы методов сравнения оба объекта должны являться числами. Со строками будет ошибка. Именно поэтому у меня применяется метод to_i.

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

number = rand(16)
# Для тестирования
puts number

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

Иду дальше по задаче. ПО условиям сказано, что если игрок не угадывает — ему даётся подсказка:

  • программа отвечает «тепло» если введенное число отличается от загаданного на 2 или меньше.
  • программа отвечает «холодно» если введенное число отличается от загаданного на 3 и больше.

Значит следующим шагом у меня в программе нужно добавить вложенное условие if else с подсказками. Если разница между загаданным числом и числом игрока не больше 2, то даём подсказку «Тепло».

Если разница больше — даём подсказку «Холодно».

Теперь код игры выглядит вот так:

number = rand(16)

# Для тестирования
puts number

puts "Приветствуем тебя в игре \"Угадайка\"! ",
"Загадано число от 0 до 15 включительно.",
"У тебя есть три попытки отгадать его."

puts "ПОПЫТКА №1: Какое число загадано?"
guess_number = gets.chomp.to_i

if guess_number == number
  puts "Ты угадал число! Молодец!",
  "Игра пройдена!"
  exit
else
  # сравниваем число игрока с загаданным числом на больше или меньше и даём подсказку №1
  if guess_number < number
    puts "Нужно число побольше ;)"
  else
    puts "Назови число поменьше ;)"
  end

  # измеряем разницу чисел и даём подсказку №2
  if (guess_number - number).abs < 3
    puts "Тепло: разница меньше трёх!"
  else
    puts "Холодно: разница больше трёх!"
  end

end

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

Для того что бы получить разницу чисел я вычитаю одно число из другого, но так как в результате может получиться отрицательное значение необходимо получить абсолютное значение. Это делается при помощи метода abs — возвращает абсолютное значение числа. Теперь каким бы не был результат, на выходе всегда положительное число, с которым можно работать: сравнивать с другими числами.

(guess_number - number).abs < 3

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

Для этого я два раза скопирую строку с методом gets и блок с условиями на проверку введённого числа. У меня получится ТРИ одинаковых блока кода. А в конце просто выведу на экран сообщение с загаданным числом.

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

number = rand(16)

# Для тестирования
puts number

puts "Приветствуем тебя в игре \"Угадайка\"! ",
"Загадано число от 0 до 15 включительно.",
"У тебя есть три попытки отгадать его."

puts "ПОПЫТКА №1: Какое число загадано?"
guess_number = gets.chomp.to_i

if guess_number == number
  puts "Ты угадал число! Молодец!",
  "Игра пройдена!"
  exit
else
  # сравниваем число игрока с загаданным числом на больше или меньше и даём подсказку №1
  if guess_number < number
    puts "Нужно число побольше ;)"
  else
    puts "Назови число поменьше ;)"
  end

  # измеряем разницу чисел и даём подсказку №2
  if (guess_number - number).abs < 3
    puts "Тепло: разница меньше трёх!"
  else
    puts "Холодно: разница больше трёх!"
  end

end

puts "ПОПЫТКА №2: Какое число загадано?"
guess_number = gets.chomp.to_i
if guess_number == number
  puts "Ты угадал число! Молодец!",
  "Игра пройдена!"
  exit
else
  # сравниваем число игрока с загаданным числом на больше или меньше и даём подсказку №1
  if guess_number < number
    puts "Нужно число побольше ;)"
  else
    puts "Назови число поменьше ;)"
  end

  # измеряем разницу чисел и даём подсказку №2
  if (guess_number - number).abs < 3
    puts "Тепло: разница меньше трёх!"
  else
    puts "Холодно: разница больше трёх!"
  end

end

puts "ПОПЫТКА №3: Какое число загадано?"
guess_number = gets.chomp.to_i
if guess_number == number
  puts "Ты угадал число! Молодец!",
  "Игра пройдена!"
  exit
else
  # сравниваем число игрока с загаданным числом на больше или меньше и даём подсказку №1
  if guess_number < number
    puts "Нужно число побольше ;)"
  else
    puts "Назови число поменьше ;)"
  end

  # измеряем разницу чисел и даём подсказку №2
  if (guess_number - number).abs < 3
    puts "Тепло: разница меньше трёх!"
  else
    puts "Холодно: разница больше трёх!"
  end

end

# расскажем пользователю, что же было загадано
puts "Попытки кончились! Ты не смог угадать число " + number.to_s

Выполнение дополнительного задания на поиск алгоритма угадывания числа за ТРИ шага

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

Как это сделать?

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

  1. кол-во попыток делим на общее кол-во вариантов числа
  2. а затем результат умножаем на 100
Вероятность угадать = (3/16)*100

Но у нас еще есть подсказки, которые увеличивают вероятность угадать. Вот только я пока не понял как это выразить в формуле ((

Пока что подвешу этот вопрос. Может попозже выясню и допишу. Но мне кажется что тут какие то задачи на применение алгоритмов. Я пока это не умею делать.

Может вы знаете?

Повторение пройденного материала

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

Вводные уроки

Записал первое видео с обзором вводных уроков и повторением пройденного материала. В принципе прикольно.

Юрий Ронин