![]() |
|
Программирование >> Рекурсивные объекты и фрактальные узоры
for(int i = 0; i < 300; i++) { TurtleCG + ToString(len) + TlO ); len += 0.1; Идея черепашьей графики восходит, по крайней мере, к языку LOGO (1966 г.). Позже аналогичные возможности были добавлены в популярные версии Бейсика. Сейчас черепаший подход нередко используют, например, при вычерчивании фрактальных изображений. Теперь осталось реализовать функцию Turtle (). Основная программа должна предоставлять возможность пользователю вводить строку на черепашьем языке и чертить соответствующий рисунок на экране. Все чис-легпшхе аргументы можно считать целыми. 5.3. КОСМИЧЕСКАЯ ДУЭЛЬ, ИЛИ ПРОВОЛОЧНАЯ ГРАФИКА В ДЕЙСТВИИ Итак, нужно запрограммировать игру для двух человек Space Duel. Суть игры заключается в следующем: в замкнутом пространстве (рис. 5.2) летают два вооружённых космических корабля. Управление каждым кораблём осуществляется с помощью пяти клавиш: поворот влево, поворот вправо, ускорение, торможение и выстрел. Изначально корабли находятся на случайных (но непересекающихся) позициях. Корабль, достигающий края экрана, отражается от него, сохраняя скорость. Угол падения равен углу отражения. Цель игры - выстрелом поразить корабль соперника. Рис. 5.2. Игра Space Duel ![]() Если хорошо подумать, можно, конечно, и здесь обойтись функциями вывода точек и отрезков, однако можно и упростить себе задачу, если изменить взгляд на саму идеологию рисования на экране. Представьте себе, что точке (О, 0) экрана находится так называемая черепашка (при работе с черепашкой обычно считают началом координат левый нижний угол экрана, ось ординат направлена вверх). Эта черепашка умеет ползать по экрану, и по первому вашему требованию направится, куда ни пожелаете. Кроме того, у неё в лапках есть карандаш, которым она может отмечать свой путь. Единого стандарта черепашьего языка пс существует, но мы вполне можем ограничиться следуюп1ими командами: и - поднять карандаш, перейдя в режим простого движения (не оставлять за собой следа); D - опустить карандаш, перейдя в режим рисования; Gn - пройти вперёд (по направлению движения) п пикселей; Та - повернуться на угол а градусов (ссли угол положительный, то влево, иначе вправо). Изначально для черепашки установлен режим простого движения, смотрит она строго вверх. В качестве простого примера программы на черепашьем языке можно привести процедуру рисования прямоугольника размером 100 х 50 пикселей: DG50T-90G100T-90G50T-90G100 Если предположить, что функция Turtle () выполняет строку команд на черепашьем языке , то спираль, изображённая на рисунке слева, будет нарисована в результате выполнения довольно простой программы на С++: вспомогательная функция преобразования числа в строку std::string ToString(int х) std::ostringstream stream; stream x; return stream.str(); void main() { перевести черепашку ближе к центру экрана Turtle( T-50G300D ); double len = 1; Программа должна загружать уровень из файла, а затем передавать упрай-ление пользователю. В случае победы выводится соответствующее сообщение. Должна быть также предусмотрена возможность начать игру заново, если играющий понимает, что он попал в безвыходное положение. Дополнительное задание. Попробуйте написать программу, которая решает уровни Сокобана автоматически. Подсказка Идеологически решение головоломки Сокобан похоже на игру в 15 (п. 4.3.1), поэтому я советую воспользоваться эвристическим поиском А*. Правда, изобрести хорошую эвристику для данной игры гораздо труднее. Насколько мне 1звестно, идеально работающего алгоритма ещё йе изобретено. Непростая работа для А* Требуется написать классическую игру Сокобан (что по-японски означает кладовщик ). Цель игры - растолкать ящики по отмеченным на уровне позициям. Уровень условно состоит из клеток, каждая из которых либо пуста, либо содержит непроходимую стену (рис. 5.3). Перемещения по уровню также дискретные: за один ход герой едвигается на одну клетку в любую из четырёх сторон. Ящики можно лишь толкать (таким образом, затолкав ящик в угол, его не удастся оттуда вытащить). Два (или более) подряд стоящих ящика с места не столкнуть (слишком тяжело). На рис. 5:3 один из шести ящиков (в правой части) уже находится в целевой позиции. ![]() MOUE 0063 PUSH 0015 TIME 0204 LEU: 01 5.5. ВИЗУАЛИЗАЦИЯ ПРОСТОГО ТРЕХМЕРНОГО МИРА Трехмерный лабиринт Пусть у нас имеется лабиринт, заданный прямоугольной матрицей из нулей и единиц (как в п. 3.2.1). Нуль означает стену, единица - проход (рис.3.2). Стартовой локацией лабиринта снова считается верхний левый угол, финишной - нижний правый. На сей раз автоматически решать лабиринт не требуется. Вместо этого предлагается написать игру трёхмерный лабиринт , позволяющую блуждать по лабиринту игроку-человеку. Программа рисует на экране текущую локацию так, как её видит путешественник (рис. 5.4). ![]() Рис 5.3. Mqta Sokt)ban Рис. 5.4. Вид лабиринта изнутри Пока выпущенный игроком снаряд находится в полёте, следующий выстрел сделать нельзя (иначе игра превратится в сплоышой обстрел). Игроку, поразившему соперника, засчитывается одно очко. Если корабли столкнулись между собой, оба корабля взрываются, очки никому не присуждаются. Взорвавшийся корабль возникает в случайном месте экрана (но, естественно, не поверх корабля соперника). Игра заканчивается, как только один из соперников наберёт пять очков. Корабли проще всего нарисовать с помощью отрезков прямых. Можно выбрать более простые формы, чем изображены на рисунке. Для движения и поворота кораблей используйте функции из п. 2.1.3 Проволочная графика . 5.4. ЭВРИСТИЧЕСКИЙ ПОИСК И СОКОБАН ![]() Рис 5.5. Внешний вид приложения Трехмерный лабиринт Большую часть формы занимает трёхмерное изображение лабиринта. Вверху расположено поле тМето, содержащее карту лабиринта с отмеченной текущей позицией путешественника. Нулями обозначаются стены, единицами - проходы. Обозначение текущей позиции зависит от направления движения: - вверх V - вниз < - влево > - вправо С алгоритмической точки зрения программа не представляет собой ничего сложного, но технические нюансы имеются. Я предполагаю, что создано приложение с главной формой Main Form, на которой расположен занимающий всю форму элемент DrawingArea типа TImage (на него будет производиться весь графический вывод), а также элемент MazeMap типа ТМето (карта лабиринта). В свойствах Мето-поля лучпге установить какой-либо мононшринный шрифт (например. Courier New), чтобы ширина карты была одной и той же для каждой горизонтали. Кроме того, карта должна быть доступна только для чтения (свойство Readonly). Основным элементом лабиринта является боковая стена (рис. 5.6). начатхо стены OuterH ![]() InnerH FrontW Рис 5.6. Боковая стена лабиринта Движение путешественника управляется курсорными клавишами: (пово рот влево на 90°, поворот вправо на 90°, шаг на локацию вперёд, разворот на 180°). Если достигаута финишная локация, выводится сообщение о победе. Необязательно реализовывать настоящую трёхмерную графику, поскольку здесь нет ни плавных поворотов, ни непрерывных движений. Достаточно выводить статичный чертёж текущей локации, а после любого действия игрока обновлять содержимое экрана (дискретно, без анимации). Для простоты можно считать, что в лабиринте нет залов , то есть прямоугольных участков без степ размером 2x2 локации или больпге. Наличие залов порождает новые проблемы. Например, если путешественник видит прямо перед собой больигос помещение, в дальнем правом углу которого располагается одрга стена, эту стену придётся как-то изобразить на экране. Если же залов нет, программе достаточно начертить: стену лабиринта прямо по курсу; набор стен и проходов по левую руку; набор стен и проходов по правую руку. Таким образом, при вычерчивании текущего вида лабиринта вполне достаточно иззчить коридор до ближайшей стены по ходу движения и содержимое ближайших клеток слева и справа от коридора . Решение Перед тем, как приступить к разработке, мне кажется разумным показать скриншот готовой программы, чтобы создать представление о том, что мы в конечном итоге должны получить (рис. 5.5).
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |