Игра «Угадай животное»

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

Итак, создадим рабочую книгу, в которую входят листы MAIN и DATA. MAIN – это лист, который будет открыт по умолчанию при запуске данной книги. На нем следует расположить кнопку, с помощью которой будет запускаться игра (подробнее об этом рассказано ниже). Здесь также можно ввести произвольный текст – например, приветствие или что-то в этом роде: Вас приветствует программа «Угадай животное» и т. п.

Содержимое листа DATA показано на рис. 5.8 (обратите внимание на координаты данных – именно на такое их расположение ориентирован приведенный ниже код программы).

Рис. 5.8. Содержимое листа DATA

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

Листинг 5.4. Игра «Угадай животное»

Sub StartGame()

Dim intLastRow As Integer ' Номер строки для вставки

записей

Dim intRow As Integer ' Номер текущей строки

Dim intYesRow As Integer ' Номер строки, из которой брать _

данные при утвердительном

ответе

Dim intNoRow As Integer ' Номер строки, из которой

брать _ данные при отрицательном ответе

Dim strText As String ' Строка с вопросом или названием _ животного

Dim strNewName As String ' Строка с названием нового

животного

Dim strNewQuestion As String ' Строка с новым вопросом

Dim intRes As Integer

' Начало игры

MsgBox «Начнем игру. Задумайте животное.», vbOKOnly, _

«Задумайте животное»

' Определение номера ряда для вставки записей. _

intLastRow-1 – номер последнего ряда, содержащего данные

intLastRow = Worksheets(«Data»).Range(«D1»).Value + 1

' Данные в таблице идут с первого ряда

intRow = 1

Do While intRow < intLastRow

' Текст вопроса или название животного из столбца "A"

strText = Worksheets(«Data»).Cells(intRow, 1).Value

' Номер ряда, из которого брать данные при утвердительном _

ответе, берем из столбца "B"

intYesRow = Worksheets(«Data»).Cells(intRow, 2).Value

' Номер ряда, из которого брать данные при отрицательном _

ответе, берем из столбца "C"

intNoRow = Worksheets(«Data»).Cells(intRow, 3).Value

If intYesRow > 0 Then

' В строке strText содержится вопрос. Зададим его

intRes = MsgBox(strText, vbYesNo, «Вопрос»)

If intRes = vbYes Then

' Переходим по утвердительному ответу

intRow = intYesRow

Else

' Переходим по отрицательному ответу

intRow = intNoRow

End If

Else

' Альтернативы закончились. В строке strText – название _

животного. Спросим, его ли загадали

intRes = MsgBox("Это " & strText & "?", vbYesNo, «Вопрос»)

If intRes = vbYes Then

' Животное угадано

MsgBox «Угадала! Спасибо за игру!», vbOKOnly, _

«Игра завершена»

Exit Do

Else

' Животное не угадали, но данные уже занкончились. _

Нужно пополнить наши данные, чтобы отличать животное _

с названием strText от загаданного

' Ввод названия нового животного

strNewName = InputBox(«Сдаюсь. Кто это?», _

«Напечатайте название животного»)

If strNewName <> "" Then

' Ввод вопроса, по которому отличать животных

strNewQuestion = InputBox("Задайте вопрос, по " & _

«которому можно отличить '» & strNewName & _

«' от '» & strText & "'","Напечатайте вопрос")

If strNewQuestion <> "" Then

' Определение, какое из животных соответствует _

утвердительному ответу на вопрос

intRes = MsgBox(«Правильный ответ на ваш» & _

"вопрос – " & strNewName & "“", vbYesNo, _

«Какой ответ на вопрос?»)

' Добавление в таблицу названия нового животного

Worksheets(«Data»).Cells(intLastRow, 1). _

Value = strNewName

' Перемещения названия животного, которое было _

ранее, в конец таблицы

Worksheets(«Data»).Cells(intLastRow + 1, 1). _

Value = strText

' Замена названия этого животного вопросом

Worksheets(«Data»).Cells(intRow, 1). _

Value = strNewQuestion

' Корректировка номеров строк для перехода _

в зависимости от того, какое животное является _

правильным ответом на введенный пользователем

вопрос

If intRes = vbYes Then

' Новое животное – правильный ответ

Worksheets(«Datа»).Cells(intRow, 2). _

Value = intLastRow

Worksheets(«Data»).Cells(intRow, 3). _

Value = intLastRow + 1

Else

' Бывшее ранее животное – правильный ответ

Worksheets(«Data»).Cells(intRow, 2). _

Value = intLastRow + 1

Worksheets(«Data»).Cells(intRow, 3). _

Value = intLastRow

End If

' Сохраним номер строки для добавления записей

Worksheets(«Data»).Range(«D1»).Value = _

intLastRow + 2

End If

End If

' Игра завершена. Таблица дополнена

MsgBox «Спасибо за игру!», vbOKOnly, «Игра завершена»

Exit Do

End If

End If

Loop

End Sub

После этого на листе MAIN создадим кнопку Старт и назначим ей макрос S tar tGame. После нажатия данной кнопки на экране отобразится окно, изображенное на рис. 5.9.

Рис. 5.9. Начало игры

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

Работа данной программы и, главное, ее «обучение» основаны на особенном строении данных, используемых этой программой. Они организованы в виде бинарного дерева. Каждый элемент этого дерева, являющийся вопросом, – узел, а элемент, являющийся названием животного, – лист. Каждый узел содержит два элемента (пусть левый и правый). При отрицательном ответе на вопрос рассматривается левый элемент, при утвердительном – правый. Если рассматриваемый элемент является узлом, то опять задается вопрос и анализируется ответ. Если же элемент – лист, то мы дошли до конца цепочки возможных вопросов и ответов, остается только спросить, является ли содержимое листа правильным ответом. В случае правильного ответа работа программы завершается. Если же ответ неправильный, то пользователь вводит вопрос, позволяющий отличить загаданное им животное от того, которое предположила программа. Название животного заменяется вопросом (на место листа дерева вставляется узел). Слева помещается название прежнего животного (лист), а справа – загаданного пользователем (тоже лист дерева). Так пополняются знания приведенной программы.

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

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