Итак, открываем Visual Studio Express и создаем новый проект — консольное приложение с именем ConsoleApplication3. Между строками Sub Main () и End Sub вставляем учебный код игры «Города» — файл с листингом программы вы найдете на «Мир ПК-диске».
В строке под номером 10 оператор Dim объявляет несколько переменных. В целочисленной переменной n будем держать число центральных городов РФ — вдруг оно увеличится. Переменные i и j — это счетчики циклов, выполняющие группу операторов несколько раз (в соответствии с диапазоном счетчика). В строковую переменную city (тип String) мы собираемся вносить название очередного города. Переменную flag объявляем как Boolean (т. е. булевой, логической). У нее может быть лишь одно из двух значений — false или true. Объявленная переменная f могла быть строковой (тип String), однако в нашем алгоритме в ячейке f будет храниться только одна последняя буква введенного города, и для такого случая оптимально использовать символьный тип данных (тип Char).
В 20‑й строке мы создаем (и сразу же заполняем) строковый массив cities () со всеми названиями центров субъектов Российской Федерации. Кстати, города идут в том же порядке, что и в 65‑й статье Конституции РФ. Разумеется, эта строка должна быть очень длинной, и, чтобы сохранить читабельность журнальной статьи, мы использовали служебный символ с нижним подчеркиванием («_»). После него командные строки Visual Basic допустимо разрывать в любом месте. Однако помните, что перед нижним подчеркиванием в обязательном порядке должен быть пробел. Список городов можно дополнить и другими названиями, тогда процесс игры станет еще интереснее.
В строке 30 задействовано свойство Length, благодаря которому мы выясняем число элементов массива cities () и записываем его в переменную n. Обратите внимание: нумерация любого массива в Visual Basic 2010 начинается с нуля. Поэтому в нашем примере в таблице cities () 80 городов-элементов, но последний из них имеет порядковый номер 79.
В следующей строке создаем вспомогательный массив goroda (), где будем учитывать использованные названия городов. Естественно, число элементов в нем совпадет с числом городов cities (). По умолчанию все логические флажки массива goroda () будут иметь значение false, но как только в процессе игры будет озвучен какой-либо город из cities (), то соответствующий по номеру элемент goroda () получит значение true. Кстати, проверку состояния элементов goroda () увидите дальше, в программных строках 290 и 460.
Теперь обратите внимание на то, как построен вывод на консоль в строке 50. Фраза склеена из трех частей. Первая и последняя — обычные строки. А чтобы между ними поместить число задействованных городов, пришлось целочисленную переменную n превращать в строку с помощью функции Str (n). Интересно, что в ряде других версий языка Basic такая операция и не нужна, а в Visual Basic слагаемые склейки придется приводить к одному типу данных.
В трех последующих строках — 60, 70 и 80‑й — представлена циклическая конструкция, удобная для вывода содержания массива cities () на консоль. В результате выполнения цикла For Each… Next на экране появится список всех центральных городов РФ. Возьмите этот шаблон для вывода массива на заметку — пригодится в будущих программах.
Список городов удерживается на экране до тех пор, пока не будет нажата любая кнопка на клавиатуре. Отслеживается нажатие благодаря команде Console.ReadKey () из 100‑й строки. Затем вызывается метод Console.Clear (), и консоль очищается.
В строке 120 разместились сразу две командные конструкции, разделенные двоеточием. Первая инициализирует генератор случайных чисел, вторая записывает в переменную i округленное до целого числа произведение случайного вещественного числа (от 0 до 1) на число элементов в массиве cities (). Иными словами, с помощью выражения Math.Round (Rnd () * (n-1) мы вытягиваем случайный номер из соответствующего списка городов для первого хода.
В строке 130 в переменную city мы записываем само название выбранного города из массива cities (). Здесь же во вспомогательный массив goroda () вносим пометку, позволяющую игнорировать определенный мегаполис в процессе будущих ходов.
В строке 140 в переменную f заносим последнюю букву избранного города. Функция Right () возвращает подстроку, содержащую указанное число знаков с правой стороны. В нашем случае Right (city, 1) — один последний символ из переменной city.
В строках 150 и 160 на всякий случай проверяем, на какую букву заканчивается случайно выбранный город. Вдруг это Казань или Чебоксары? Тогда нужно брать не последнюю в названии, а предпоследнюю букву. Это можно сделать с помощью другой функции — Mid (city, city.Length-1, 1). Она из переменной city возвращает строку из одного знака, начиная с позиции city.Length-1 (длина названия города минус один).
В строке 170 сообщаем правила нашей игры и стартовый город.
Все инструкции между строками 180 и 600 — главная часть нашего алгоритма. По логике программы ход человека и ответ компьютера многократно повторяются в цикле. Очевидно, что число исполнений тела цикла не может превышать количество городов-элементов в массиве cities (). Именно поэтому счетчик ключевого цикла запущен с 0 до n-1 — по умолчанию шаг цикла равен единице.
Командный кусочек — со 190‑й по 420‑ю строку — ход человека, с 430‑й по 590‑ю строку — отклик компьютера. Обе половины схожи. Строки 190 и 430 — здесь сбрасываем логический флажок. В строках 200 и 440 устанавливаются разные цвета для вывода текста на консоль и т. д.
В строке 220 считываем с консоли название города в переменную city. Следом введенное слово переводим в нижний регистр с помощью метода ToLower.
Строки 240—420 — конструкция ветвления в зависимости от последней буквы в обновившейся переменной city. Если человек указал город, первая буква которого не совпадает со значением переменной f, хранящей последнюю букву от прошлого города, то пользователь увидит сообщение: «Вы проиграли…». Первую букву в переменной city выясняем с помощью метода Left (city, 1).
В строке 260 находится важный оператор Exit For. По нему происходит немедленный выход из цикла For, и выполнение алгоритма продолжается с команды, следующей за оператором Next, т. е. переходим к завершающим строкам 610 и 620. Кстати, при использовании вложенных циклов For команда Exit For закрывает самый внутренний цикл и передает управление следующему уровню вложения.
Строки 280—410 будут выполняться, если в ответе человека первая буква в названном городе совпадет с переменной f. Запускается вложенный цикл (строки 280—370), в котором перебираются абсолютно все элементы массива cities (). Метод cities (j). ToLower приводит название города к нижнему регистру для корректного поиска. Помимо вхождения значения city в список городов, программа смотрит на значение соответствующего элемента из массива goroda (). Если название мегаполиса уже звучало в игровом процессе, то ячейка goroda (j) должна быть в значении true. По пути проверяется сигнальная переменная flag. Если она находится в положении true, то мы уже одобрили ход человека и вычеркнули названный город из списка оставшихся.
Когда исполнитель алгоритма попадет в строки 300—350, на экране появится одобрительная фраза: «Знаю такой город. Название принято» (строка 300). Соответствующий элемент массива goroda (j) и переменная flag получат значение true (строки 310 и 320). В переменной f возникнет последняя буква названного города (строка 330). Назначение строк 340—350 аналогично строкам 150—160.
Если после выполнения циклической конструкции (строки 280—370) значение флажка f будет равно false, значит, человек не смог назвать подходящий город. Будут исполнены команды из строк 390 и 400. Появится сообщение: «Вы в проигрыше», а далее Exit For отошлет вас к концу проекта (т. е. к строке 610).
Как отмечено выше, фрагмент программы между строками 430 и 590 — ответный ход компьютера. В строке 430 сбрасываем флажок flag, а в 440‑й устанавливаем зеленый цвет шрифта для компьютерных ответов. В цикле (строки 450—550) перебираем города из массива cities (), ищем подходящее название, чтобы последняя буква города, введенного человеком, совпала с первой буквой элемента cities (j). При этом алгоритм следит за соответствующим значением goroda (j) — вдруг этот город был назван. И еще наблюдаем за состоянием переменной flag.
По большому счету компьютер проиграет лишь тогда, когда кончатся все подходящие города из массива cities (j) — запустятся команды из ветки (строки 560—590). Иначе программа найдет правильный ответ (строка 460), выведет его на экран (строка 470) и в элемент goroda (j) и переменную flag запишет значения true (строки 490 и 500). И самое главное, компьютерный ход отразится в переменной f — в нее попадет последняя буква названного города (строка 330). Если последней будет буква «ь» или «ы», то в f запишем предпоследнюю букву из названия города (строки 520 и 530). А далее Next i из строки 600 и возврат к строке 180 — круг замкнулся.
Отметим, что в игре возможна ничья. Это в случае, если все города названы и выход из главного цикла (строки 180—600) осуществится сам по себе, за счет перебора всех значений счетчика i от 0 до n-1. Тогда на экране появится лишь одна дежурная надпись: «Игра окончена. Нажмите Enter», после чего компьютер будет ожидать нажатия клавиши Enter за счет оператора Console.ReadLine () из последней строки (под номером 620). Кстати, вопрос для внимательных читателей: чем Console.ReadLine () отличается от Console.ReadKey ()?
В завершение повествования предложу вам самостоятельную работу — попробуйте сделать игру «Столицы мира» и подумайте, как обойтись в ней без вспомогательного массива goroda (). Например, можно просто затирать названия использованных городов.
Вот, пожалуй, и все. Возникнут вопросы по алгоритму — вдумчиво перечитайте статью. Если будут сомнения по поводу предназначения различных операторов, встаньте курсором на нужном месте и нажмите клавишу