App Inventor/Угадыватель чисел

В этой главе мы познакомим вас с программой «Угадыватель чисел», идея которой взята из книги Л. Ф. Магницкого, «Арифметика»[1]. Опишем задачу и расскажем как запрограммировать решение. Поработаем с экранами приложения, создадим процедуры и покажем как разрешить ввод только числовых значений в программе.

Игра "Угадыватель чисел" (App Inventor). Автор: Оксана Панфилова.

Описание задачи править

Суть предлагаемой нами задачи описана в книге Л. Ф. Магницкого «Арифметика», в главе: «Об утешных некиих действиях, через арифметику употребляемыx»[1].

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

Номер шага Действие Арифметическое преобразование
1 Умножить номер загаданного дня недели на два. Пусть   — искомое число (день недели),  . В результате выполнения шага 1 получаем  
2 К полученному произведению прибавить пять.  
3 Затем полученную сумму умножить на пять.  
4 Полученное число умножить на десять.  
5 Назвать результат вычислений.

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

 

Таким образом, с помощью этих арифметических преобразований мы определили, какое число загадал игрок ( ).

Реализация приложения править

В программе «Угадыватель чисел» (The Numbers Guessing Game). загаданный игроком номер дня недели — это то, что мы будем искать.

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

Определение числа, загаданного игроком править

 
Рис. 1: Блок обработки нажатия на кнопку Button1.
 
Рис.2: Процедура VisibleFalseImages.

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

Рассмотрим блок обработки нажатия (рис. 1) на кнопку «Узнать ответ» (Button1). Когда игрок нажимает на эту кнопку, последовательно выполняются следующие действия:

  1. Вызываетcя процедура VisibleFalseImages (рис. 2), которая устанавливает свойство Visible у всех изображений с цифрами в false. Таким образом, пока не будет определено число, загаданное пользователем, изображения с цифрами не будут отображаться.
  2. Устанавливается свойство Visible в значение true у изображения со знаком вопроса (Image8).
  3. Если значение поля для ввода загаданного числа (NumberText) пусто, то приложение сигнализирует пользователю об ошибке следующим образом. Устанавливаем красный цвет шрифта, чтобы стало видно сообщение «Пожалуйста, введите полученное число.» у поля ErrorLabel (рис.4). В случае, когда что либо введено в поле NumberText, последовательно выполняются следующие шаги:
    1. Устанавливается белый цвет шрифта у поля ErrorLabel.
    2. Производится подсчёт значения переменной SecretNumber:
    3. Вызывается процедура SelectVisibleImage, которая будет рассмотрена далее.

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

Процедура SelectVisibleImage править

Процедура SelectVisibleImage (рис. 3) читает значение глобальной переменной secretNumber и отображает рисунок с соответствующей цифрой.

 
Рис. 3: Процедура SelectVisibleImage. Пунктирной линией отмечены однотипные блоки управления, выполняющие действие по установке значения свойства Visible в true у изображения с числом, которое сравнивается с переменной SecretNumber. Такие блоки можно увидеть на изображении для чисел один и семь.
 
Рис.4: Сообщение об ошибке на экране FinalScreen.
 
Рис.5: Сообщение об ошибке в расчётах на экране FinalScreen.

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

Например, пусть игрок загадал число три. На основании введённого пользователем числа в поле NumberText на экране FinalScreen (в этом примере должно быть введено число пятьсот пятьдесят) приложение подсчитает и присвоит переменной SecretNumber новое значение, равное трём. Процедура SelectVisibleImage в соответствие со значением переменной secretNumber делает видимым изображение с соответствующей загаданному числу цифрой. В нашем примере это изображение числа три (Image3). Если переменная SecretNumber содержит в себе значение, не входящее в интервал от одного до семи, то будет показано изображение со знаком вопроса (Image8), а текст надписи ErrorСalculating станет видимым («Допущена ошибка в расчетах. Попробуйте снова.», рис. 5).

Важно отметить, что перед выполнением условий сравнения переменной secretNumber с введённым пользователем числом, выполняется установка свойства Visible в false у элементов Image8 и ErrorСalculating (рис. 3). Тем самым мы отмечаем отсутствие ошибок в вычислениях и заранее убираем с экрана знак вопроса, предполагая, что на его месте будет изображение с определённой цифрой. Если же переменная SecretNumber не входит в интервал от одного до семи, то у элементов Image8 и ErrorСalculating устанавливается значение свойства Visible в true, так приложение сообщает пользователю о его ошибке в вычислениях.

Работа с экранами править

При проектировании приложения были учтены рекомендации из официальной документации App Inventor по ограничению количества экранов во избежание проблем с переполнением памяти. Поэтому в игре используется восемь экранов (рекомендуемое количество — меньше 10):

  1. Screen1 — главный экран приложения, меню игры.
  2. About — экран, содержащий информацию о приложении.
  3. Step1, Step2, Step3, Step4, Step5 — это экраны с пошаговым описанием задания пользователю. На экранах есть следующие кнопки для навигации между экранами приложения:
    1. «На шаг назад» (PreviousStepButton) меняет экран на предыдущий.
    2. «Далее» (NextStepButton) — переход игрока на следующий экран.
    3. «В главное меню» (BackToMainMenuButton) показывает пользователю главный экран Screen1.
  4. FinalScreen — — это экран с результатами игры. Здесь пользователю необходимо ввести получившееся в результате вычислений число и нажать кнопку «Узнать ответ», чтобы увидеть на экране число, которое по предположению программы загадал игрок.
Упражнение. Приложение можно перепроектировать таким образом, чтобы экраны Step1, Step2, Step3, Step4, Step5 представляли собой один экран. Попробуйте реализовать приложение «Угадыватель чисел» с одним общим экраном Steps, который будет при нажатии на нём кнопок навигации последовательно показывать пользователю пошаговую инструкцию по преобразованию загаданного числа.

Если вызывать блок управления среды App Inventor для открытия другого экрана («open another screen»), а затем не вызывать блок управления для закрытия экрана («close screen»), то через некоторое время приложение израсходует всю доступную память.

Рассмотрим решение этой проблемы в нашем приложении. Экран Screen1 содержит в себе названия игры и две кнопки: «Старт» (StartButton для перехода на экран Steps) и «Об игре» (AboutButton для перехода на экран About).

 
Рис. 6.: Процедура CloseScreen.

Для того, чтобы не получить ошибку переполнения памяти, создадим процедуру для закрытия экрана, которую назовём CloseScreen (рис. 6). Она будет содержать в себе один единственный блок управления close screen. Возникает вопрос: зачем действие по закрытию экрана помещать в отдельную процедуру? Это необходимо для того, чтобы последовательно выполнить блоки управления «open another screen» и «close screen» при возникновении события нажатия на любую навигационную кнопку (Click). «Пазлы» блоков управления открытия и закрытия экрана спроектированы так, что их нельзя объединить в одном блоке App Inventor, но можно соединить их через вызов процедуры, что и было сделано (рис.6).

Упражнения править

1 В параграфе «Решение задачи» в доказательстве алгоритма определения загаданного игроком числа говорится, что   — это искомое число, но не уточняется, какое именно. К какому виду принадлежит число  ?

натуральное число.
рациональное число.
действительное число.
целое число.

2 В параграфе «Реализация приложения» была описана процедура SelectVisibleImage? К какому типу процедур она относится?

Procedure ‒ процедура, не возвращающая значение.
ProcedureWithResult ‒ процедура, возвращающая какое-то значение.

3 На рисунках изображены различные блоки, предназначенные для создания приложений в среде App Inventor. Определите, к какому виду принадлежит каждый из них.

Блок компонента / Встроенный блок (built-in)
 
 
 
 


Примечания править

Ссылки править

Литература править

Галанин Д. Д. Вып. 2 — Арифметика-политика, или гражданская. Вып. 3 - Арифметика-логистика. // Леонтий Филиппович Магницкий и его арифметика.. — М.: Типография О. Л. Сомовой, 1914. — С. 109. — 207 с.