Интересные проекты «змейка» для терминала, работающая на этапе компиляции


Оглавление (нажмите, чтобы открыть):

игра змейка (есть ли у кого исходник?)

09.01.2010, 20:02

Есть ли тут такие, у кого есть свои идеи ,касающиеся компьютерной безопасности,например, по защите от вирусов?
Есть ли тут такие, у кого есть свои идеи ,касающиеся компьютерной безопасности,например, по защите.

Игра змейка. У кого нибудь есть исходник?
Игра змейка. У кого нибудь есть исходник? Интересует только JAVA. Заранее благодарен.

У кого есть исходник по БД Кинофильмы
Народ, может кто скинуть исходник программы «Кинофильмы», «Видеофильмы» или что-то подобное? Очень.

Есть ли у кого-нибудь исходник кроссворда?
Всем привет. Есть ли у кого нибудь исходник кроссворда, буду благодарен. Очень нужна помощь!

У кого есть исходник программы с dbimage?
Народ всем привет,у кого есть исходник программы с dbimage. Дайте плз)))буду очень благодарен)

Игры в терминале Linux. Тетрис, ПэкМен, Змейка

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

Тетрис — bastet

Тетрис в терминале — bastet. Правила классические. Два уровня сложности. Можно менять клавиши управления. Есть таблица рекордов.

Установка (выберите соответствующую команду для вашего дистрибутива):

ПэкМен — pacman4console

Клон игры Pac-man в терминале — pacman4console. Чтобы запустить игру, необходимо изменить размер окна терминала — сделать его вертикальным (минимум 29×32). Если размер меньше требуемого, то будет выведено соответствующее предупреждение.

Установка pacman4console в Linux (выберите соответствующую команду для вашего дистрибутива):

Управление клавишами стрелок.

Чтобы пройти уровень, нужно съесть все точки. Попадание на врага — потеря жизни. Звездочки — это бонусы.

Змейка — nSnake

Игра Змейка в терминале — nSnake. Она же называется еще Питон и Удав.

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

В игре есть целый набор разных уровней. Чтобы они стали доступны в игре, их нужно скопировать в свою домашнюю директорию в папку .local/share/nsnake/levels/ . Для этого можно выполнить команду (и перезапустить игру):

Кроссплатформенная «Змейка»

Появилось немного свободного времени, и я переписал «Змейку» с использованием кроссплатформенной библиотеки curses. Для Винды был использован порт PDcurses.

К сожалению у меня нет возможности откомпилировать и оттестировать программу под Линуксом. Если кому не лениво, протестируйте пожалуйста.

Проект сделан под Code::Blocks. Винда определяется по символу _WIN32 . Если символ не определён, то считается, что это Линукс. Библиотека curses ( NCurses ) в состав проекта не включена. Порт conio для *nix я не использовал. Для компиляции в проекте надо указать, что должна быть подключена эта библиотека, и надо убрать подключение pdcurses.a . В остальном, как я надеюсь, должно откомпилироваться и запуститься без проблем. А если таковые будут, напишите, что пошло не так.

PS. Общие впечатления от curses/NCurses/PDcurses — тяжёлые.
PS2. Ещё о портировании Змейки на Линукс была тема на форуме.

Здавствуйте.
Ваш код прекрасно компилируется и запускается, но работать не хочет:

А пока позвольте излить негодование по поводу вашей фразы 🙂

Общие впечатления от curses/NCurses/PDcurses — тяжёлые.

Ну они и должны быть тяжёлыми, поскольку это старая низкоуровневая библиотека, которая создавалась, видимо, когда С++ ещё даже не было.
Но всё же мне показалось, что её использование не такое уж и сложное, в какой-то степени даже удобное для новичка, не привыкшего к ООП (мне, например).

P.S.: Кстати, у меня была идейка сделать эту библиотеку объектно-ориентированной. То есть все сущности (такие как окна и панели) занести в классы (тогда можно будет избавиться от функций с приставками w). А затем занести все эти классы в какое-нибудь пространство имён, например, curses .

Вобщем, я тут покумекал, и нашёл, что программа прекрасно работает, просто результат её работы у меня не видно. Он отображается чёрным текстом на чёрном фоне 🙂
Я думаю, проблема в функции text_attr . Видимо, её вызов в main получился не совсем кроссплатформенным.

Да, догадка подтвердилась, если убрать вызов метода text_attr объекта screen в main , то получится самая настоящая змейка белыми символами на чёрном фоне:

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

Спасибо, porshe, за тестирование.

Значит PDcurses не на 100% совместима с ncurses (( У меня всё работает нормально. Можно, конечно попробовать в main вместо screen.text_attr((short)0x0a) попробовать screen.text_attr((short)0x02) — должен быть темно-зелёный цвет вместо яркого. Или при портировании вообще изменили схему кодирования цветов. Если так, то печально.

Глюк с выводом статистики в игровом поле у меня тоже проявлялся, но исключительно при работе из-под отладчика. Я списал это на некий конфликт библиотеки с отладчиком. Как оказалось, я был не прав.

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

Или, вариант второй, я где-то что-то не дочитал в доке по curses (кстати, отвратительная дока).

А пока позвольте излить негодование по поводу вашей фразы 🙂

Общие впечатления от curses/NCurses/PDcurses — тяжёлые.

Я только высказал своё личное впечатление.

P.S.: Кстати, у меня была идейка сделать эту библиотеку объектно-ориентированной. То есть все сущности (такие как окна и панели) занести в классы (тогда можно будет избавиться от функций с приставками w). А затем занести все эти классы в какое-нибудь пространство имён, например, curses.

Идейка неплохая. Только будь готов к тому, что придётся полностью перелопатить весь код библиотеки. Причём под несколько платформ. Мне кажется, что, например, с тестированием под OS/2 у тебя будут проблемы ))

А просто делать ООП-обёртку — замучаешься с глюками бороться.

Баг с неправильным позиционированием статистики я вроде поборол.

Файл CScreen.h, определение класса:

Файл main.cpp, строка 27:

Видимо под Линуксом по умолчанию для окна консоли отводится 24 строки. А под Виндой — 25.
Теперь в main игра будет подстраиваться под текущие настройки консоли.

Ещё в коде библиотеки нашёл странную фичу (это Windows-specific):

Оно, с какого-то пня, определяет через getenv , что у меня в консоли 24 строки. Откуда оно берёт переменную окружения LINES — я так и не понял, похоже, что это происки Code::Blocks. Причём, если всё свернуть до прямого вызова PDC_get_rows() , который использует виндовую GetConsoleScreenBufferInfo() , то работает правильно. Шарада, мля (

попробовать screen.text_attr((short)0x02) — должен быть темно-зелёный цвет вместо яркого.

Да, так работает.

И, собственно, у меня вопрос: почему вы не пользуетесь стандартными константами цветов? (COLOR_GREEN, к примеру). Ведь используя прямые значения (0x02, например) получается непереносимый (либо плохопереносимый) код.

porshe, ещё раз спасибо за тестирование.

почему вы не пользуетесь стандартными константами цветов?

Наверное это атавизм предыдущей (виндовой) версии )))
Конечно надо пользоваться именованными константами.
Как бы туда ещё повышенную яркость для цвета прикрутить.

Как бы туда ещё повышенную яркость для цвета прикрутить.

По-моему, attrset должна работать и с константами атрибутов. То есть можно установить атрибут A_STANDOUT , вроде.

Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.

Змейка на C

Тем, кому не интересно читать пост, а интересно сразу увидеть код и/или историю коммитов, предлагаю пойти поглядеть на репозиторий.


Небольшой дисклеймер

Да, я в курсе, что можно добавить множество разных фич (в том числе мультиплеер и уровни с процедурно генерируемыми стенками) и много чего сделать лучше как в самой игре, так и в исходниках. Возможно, я когда-то это и сделаю. На данный момент ничего особо примечательного в коде нету, потому и stupid-snake
Но была поставлена цель сделать не максимально хорошо и качественно, а быстро и чтобы работало. Ну и ещё по возможности наглядно — идея написать пост всплыла с самого начала. Эта цель в полной мере достигнута.

Немного пояснений

C — довольно низкоуровневый язык, и уж никак не «кроссплатформенный по-умолчанию», как, например, Python. Тот факт, что я не использую ncurses, ещё больше усугубляет ситуацию.
Очень многое в игре реализовано путём функций, имеющихся лишь в POSIX-системах, а то и вообще лишь в Linux и glibc. Windows POSIX-системой не является, да и терминал там вряд ли настолько же функционален, потому собрать stupid-snake под Windows у вас, скорее всего, никак не получится. На OS X — не знаю, пусть кто-то попробует и доложит об успехах.
Может также и не на каждом дистрибутиве Linux собраться, в таком случае напишите мне — помогу и добавлю нужные флаги в мейкфайл.

Если своего линукса у вас нигде не завалялось, а испытать игру очень хочется, рекомендую использовать VirtualBox или иной софт для работы с виртуальными машинами, какой вы предпочитаете.
Если же вам интересен сам процесс и разъяснения к коду — вы совершенно ничего не теряете, читая этот пост хоть с Windows, хоть с Linux, хоть с OS/2.

Почему терминал? Почему даже без ncurses? Зачем так усложнять себе жизнь?
Во-первых потому, что мне так захотелось. Во-вторых потому, что ncurses — это очень большая, толстая и сложная либа, так что не факт, что было бы проще. Пояснять, скорее всего, стало бы лишь сложнее.

Я пойму пост, если не знаю C?
Понятия не имею. Если вы действительно не знаете ни C, ни преступно подобных ему языков (типа C++) — напишите, пожалуйста, поняли вы или нет. Мне интересно.
Пост планировался как понятный полным «чайникам», но получилось ли у меня — совсем другой вопрос.

Если я прочитаю пост, я выучу C?
Нет.

Если я прочитаю пост, я научусь писать игры?
Нет. Скорее всего.

Зачем тогда мне читать пост?
Откуда я знаю, зачем вам читать пост? Может, вам интересно смотреть, как другие люди мыслят и решают задачи. Может, вам интересно узнать, какой это он — C в консолечке юниксовой. Может, просто скучно.
Впрочем, я думаю, в моём посте можно будет отыскать некоторые интересные факты и подходы, до сих пор вам неизвестные.

Какъ собрать и запустить ваше игрище бѣсовское, сударь?
Для бояр, которые этого до сих пор никогда не делали, а гуглить лень, кратенькое пояснение:
$ git clone ‘https://gitlab.com/saxahoid/stupid-snake.git’
$ cd stupid-snake
$ make
$ ./snake

Управление?
Стрелки, выход — Ctrl+C или врубиться в стенку/себя.

А вот я вижу место, где как-то очень хитроподвывернуто сделано, нельзя ли проще?
Скорее всего, нет. Как я дальше поясню в посте, в процессе разработки вылезло несколько очень интересных особенностей работы с терминалом, и эти хитроподвывернутые костыли — единственный рабочий вариант.

Поехали

Давайте-ка сделаем игру

Что нужно, дабы сделать игру для терминала? Знать какой-нибудь язык программирования более-менее уверенно и уметь гуглить, чтобы разобраться с некоторыми особенностями этого самого терминала.
Знать кучу библиотек (ну разве только ncurses, если хочется более серьёзную игру, чем у меня, с минимумом геморроя), особенности работы вашей любимой оконной системы, да ещё заодно щедрую дозу компьютерной графики и уж тем более быть дизайнером-художником абсолютно не обязательно и даже вредно. Потому что так не интересно.

Текстовый ввод/вывод — один из самых простых и основных для любого современного ЯП. Если вы уверенно (да даже если криво сикось накось) знаете какой-нибудь, то вы знаете и как работать с текстом. Поэтому для создания игры, использующей текст для общения с пользователем, не нужно знать ничего специфичного. Поэтому же такие игры, даже если примитивные по сегодняшним меркам, становятся неплохими упражнениями для мозга.

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

Дизайн

Прошу заметить, что имеется в виду не тот дизайн, которым занимается Артемий Лебедев, а технический дизайн. Оно же проектирование.

На этапе дизайна структура программы обдумывается «на бумажке», без написания рабочего исполняющегося кода (шаблоны делать можно). Такой подход кажется непродуктивным, но, если хорошо им овладеть, можно избавить себя от множества «Эврика!»-моментов, когда половину всех исходников приходится переписывать из-за неверно выбранного в самом начале решения. А потом ещё разок. Затраты на такое растут с размерами проекта очень нехило, так что частенько даже несколько месяцев чистого дизайна окупаются сполна.
В идеале садиться за код разработчик должен лишь тогда, когда уже полностью представляет себе программу.

Комплексная задача (игра «Змейка») разбивается на более мелкие:
• Обновление экрана;
Очевидно, для того, чтобы игра была динамической и отвечала на пользовательский ввод, нужно периодически обновлять экран. Так как «змейка» — не походовая забава, делать это необходимо по таймеру.
На нашем ламерском уровне более чем достаточно воспользоваться командой вроде sleep (приказать программе ничего не делать 1/fps часть секунды, где fps — желаемая кадровая частота), но это неинтересно и вообще я болею перфекционизмом, потому буду использовать часы реального времени.

• Визуализация змейки;
Терминал современного Linux поддерживает юникод — вот уж где простор для фантазии! Но по моему мнению реализация юникода в самом C не то чтобы очевидная, потому (для начала, во всяком случае) решаю использовать самый стандартный из всех стандартов — ASCII. Прямое тело змеи изображать буду символами «-|», повороты — «/\», направленную в разные стороны голову (распахнутую пасть) — «V «.
На том бы и остановиться, вот только неинтересно (и я болею перфекционизмом, помните?). Нужна ещё анимация. Как насчёт заставлять змейку закрывать рот каждый ход? Досточно будет заменить символ «головы» на соответствующий направлению символ «тела». Переход » — строки со 121 по 219
Эти четыре функции очень схожи между собой. Они устанавливают новое направление головы змеи и рисуют новый сегмент тела на месте головы, если определённый поворот возможен из нынешней позиции. Возвращают int, работающий в качестве булевой переменной (можно было бы обойтись char, но мне почему-то захотелось int).

Рассмотрим на примере turn_right [196]. Определяется нынешнее направление движения [201], и в зависимости от него определяются дальнейшие действия. Если змея двигалась вертикально (вверх [202] или вниз [205]), поворот вправо возможен — turn_right вернёт 1 и установит соответствующий повороту сегмент тела на поле. Если змея и так двигалась вправо или вообще получила неправильный аргумент [210], turn_right просто вернёт 1 и ничего больше не сделает (это нужно для эффекта ускорения при нажатой клавише). Если змея двигалась влево [208], поворот направо невозможен — turn_right вернёт 0.

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

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

process_key — строка 223
Эта функция считывает с терминала три байта [227] (именно тремя байтами кодируется нажатие клавиши-стрелки). Если эти три байта соответствуют одной из заранее определённых констант [55], вызывается функция соответствующего поворота.
Очень важно, что в данном случае переменная c инициализируется в 0: так четвёртый байт, который не считывается, но всё равно остаётся «болтаться», будет нулевым и не станет мешать. Вместо переменной int можно было использовать массив char, но сравнивать с трёхбайтными константами его намного сложнее, чем простым switch.

Возвращает функция 1 или 0 в зависимости от того, смогла ли сдвинуться змея в ответ на нажатие клавиши.

init_playfield — строка 251
Простенькая функция инициализации игрового поля. Просто забивает его всё пробелами.

init_snake — строка 259
Функция посложнее, инициализация змеи. Голова змеи устанавливается в условный центр поля и изначально смотрит вправо. Ровно в ту же позицию помещается хвост, длина змеи устанавливается в 1 и буфер длины — в 4. Таким образом, начальная длина змейки — 5.

redraw_all — строка 278
Функция отрисовки игрового поля.

Вначале курсор помещается в стартовую позицию 0, 0 (верхний левый угол) с помощью ещё одного управляющего спец-символа [279]. Далее за несколько циклов выводятся сначала верхняя стенка [281], затем боковые и само поле [286], затем нижняя стенка [295] и немного информации: длина змеи, уровень [300]. Ничего интересного здесь нет; такое писал каждый, кто когда-либо выводил матрицы на экран.

redraw_animation — строка 305
Немного более интересная функция, которая отвечает за анимацию.

С использованием, опять же, спец-символа (но в этот раз динамически сгенерированного) курсор устанавливается на координаты головы змеи [307] (поправки +2 нужны из-за того, что в змее хранятся координаты относительно игрового поля-матрицы, а нужны координаты относительно экрана). Далее вместо головы рисуется «закрытый рот» (просто сегмент тела, соответствующий направлению) [309].

Затем курсор путём всё той же манипуляции со спец-символом устанавливается на позицию змеиного хвоста [317] и с хвостом происходит анимация выпрямления (при условии, что он ещё не прямой), в общем-то идентичная таковой для головы.

move_snake — строка 338
Самая сложная, интересная и важная функция. Перемещает змею в игровом поле и вообще обновляет её состояние.

Если направление змеи не менялось (поля dir и new_dir одинаковы), значит, была нажата клавиша того же направления, либо не была нажата никакая. В обеих этих случаях функции turn_ ничего не рисуют, потому необходимо нарисовать новый сегмент тела [345-350]. Не рисуют turn_* именно потому, что возможных случая тут два (нажата та же, либо не нажата никакая), и во втором случае turn_* вызваны не будут. Получается, для этого второго случая отрисовку внутри move_snake предусматривать всё равно придётся, а раз она тут уже нужна, зачем повторно в turn_*?
Если же направление поменялось, new_dir сохраняется как dir [352].

Далее определяется символ для отображения головы и обновляются её координаты («голова сдвинулась на новое место»). Это зависит исключительно от направления головы и обрабатывается простым switch [357].

Затем новая позиция головы анализируется. Если там на данный момент стена [379], еда [392] или что угодно ещё кроме пробела (это может быть только тело змеи во всех его разнообразных вариациях) [397], выполняются соответствующие действия (game over или съедение еды). Встреча со стеной определяется как выход за рамки позволенных координат (это позволяет, например, очень легко не рисовать стены или заменить символ стены на какой-то ещё, да к тому же позволяет не занимать память зазря символами стен, никогда не меняющимися).

Наконец, после того как все возможные проблемы с новой позицией улажены (и game over не наступил), туда помещается голова змеи [407].

И теперь обрабатывается хвост [411]. Если у змеи не пустой буфер длины, она должна вырасти; в этом случае с хвостом ничего не происходит и он остаётся на старом месте [412]. Если же буфер пустой, всё намного интереснее.
Первым делом хвост заменяется пробелом [415]. Затем координаты хвоста обновляются, чтобы он занял новую позицию: следующий после старого хвоста сегмент тела [418]. Этот switch очень похож на таковой для головы [357], но ничего не рисуется.
Дальнейшая задача — определить новое направление хвоста. Сделать это можно, проанализировав сегмент на новой позиции. Если он прямой, направление хвоста остаётся прежним [437-439]. Если он «/», новое направление определяется в зависимости от старого [441]. Если он «\», направление определяется аналогично, но с другими значениями [359].

Например, если хвост двигался вверх, но выглядит как «/», то дальше ему нужно двигаться вправо.

Мастер Йода рекомендует:  20 лучших эмуляторов iOS для запуска приложений iOS на PC

gen_food — строка 483
Функция генерации пищи. Она управляется константой FOOD_RARITY, определяющей частоту еды на поле как «на FOOD_RARITY доступного пространства должен приходиться 1 юнит пищи». Соответственно, необходимое кол-во еды определяется простым делением [487]. +1 там нужно для округления вверх (то есть чтобы, например, при установленной FOOD_RARITY 512 и размере поля 600, на нём был не 1, а 2 куска еды).

Если еды на поле недостаточно (следить за её количеством можно через переменную food_cnt), генерируется новый кусок [490]. Координаты еды определяются генератором случайных чисел и подгоняются в заданные координатные рамки путём операции суммы по модулю (%), или же остатка. Полученная позиция проверяется, и если она пуста — туда помещается пища, а если занята — генерация выполняется вновь.

Из-за того, что генерироваться еда будет «до упора», в случае, близком к победе (всё поле занято змеёй), игра может начать тормозить, а когда места для необходимого кол-ва еды просто не останется, банально уйдёт в бесконечный цикл. Если вы когда-либо добьётесь такой ситуации — вы победили! И удачи с выключением игры, Ctrl+C не сработает — он перехвачен.

level_up — строка 502
Довольно простая функция, повышающая игровой уровень (а значит — скорость) по достижению змеи очередной LVLUP_LENGTH. Например, в моём случае LVLUP_LENGTH установлена в 50 — так левелап будет происходить каждые 50 очков длины.

Исползуется static (сохраняющая своё значение меж вызовами функции) переменная upped_already, чтобы избежать проблем при нескольких вызовах level_up за те хода, пока длина змеи сохраняется кратной LVLUP_LENGTH. Она устанавливается в 1 после повышения уровня, и в 0, когда длина змеи не соответствует нужному для левел-апа значению. Так как длина может лишь расти, это адекватный подход.

Послесловие

Надеюсь, кому-то было интересно прочитать про то, как можно упорото и хардкорно написать змейку.

Я для себя выношу одну истину: писать посты про свой код очень сложно. Мне было физически тяжело возвращаться к этому посту и пытаться выразить в словах то, что кажется очевидным из структуры программы. Возможно, в другой раз я попробую какой-нибудь иной формат.

Курсовая работа: Разработка приложения, представляющего собой компьютерную игру «Змейка»

ФЕДЕРАЛЬНОЕ АГЕНСТВО ПО ОБРАЗОВАНИЮ

Государственное образовательное учреждение

Высшего профессионального образования

«Нижегородский государственный университет им. Н.И. Лобачевского»

Кафедра «Экономическая информатика»

по дисциплине: ВМиП

(вычислительные методы информатики и программирования)

Разработка приложения, представляющего собой

компьютерную игру «Змейка»

Выполнил( ла ) студент(ка) курс


группы, очного отделения

СОДЕРЖАНИЕ

2. Постановка задачи

3.Опиание алгоритма решения в псевдокоде(команды в виде текста на русском языке

4.Исходный текст программы на С

Введение в объектно-ориентированное программирование.
Объектно-ориентированное программирование представляет собой чуть более автоматизированный способ программирования. Объектно-ориентированные программы – это не просто процедурные программы, переведенные на новый синтаксис. Они должны строится на новой философии разработки. Для них требуется новая стратегия программирования, которую часто бывает трудно освоить

Основная идея ООП: программа состоит из группы объектов, часто связанных между собой. В С++ объекты описываются при помощи нового типа данных class. Класс включает в себя набор переменных (данных) и операций (методов или функций-членов), которые действуют на эти переменные. Полученными объектами можно управлять при помощи сообщений. В ООП объекты включают в себя не только данные (данные-члены), но и методы (функции-члены) воздействия на эти данные. Эти две части в сочетании образуют функциональную единицу программы. Другими словами, объекты содержат данные и методы работы с этими данными. Ниже приведены три основных преимущества объектно-ориентированных программ по сравнению с эквивалентными программами, разработанными сверху вниз.

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

Модификация программы (добавление или исключение возможностей). Вы можете часто делать дополнения или исключения в программе, например при работе с базой данных, просто добавляя и исключая объекты. Новые объекты могут наследовать все свойства базовых объектов, необходимо только добавить или убрать отличающиеся свойства. Повторное использование. Можно сохранить грамотно разработанный объект в наборе полезных программ и затем вставить его в новую программу с небольшими изменениями или без изменений..

Основные термины и положения ООП. Инкапсуляция данных. Этот термин включает в себя логическое связывание данных с конкретной операцией. Она так же означает, что они являются не -глобальными доступными всей программе, а локальными – доступными только малой ее части. Инкапсуляция также автоматически подразумевает защиту данных. Именно для этого предназначена структура class в С++. В классе управление функциональными деталями объекта осуществляется при помощи спецификаторов private, public, protected.

Иерархия классов. В общем случае можно представить себе иерархию классов как родословную в генеалогическом древе, где класс С++ представляет собой шаблон для создания классов-потомков. Объекты, полученные из описания класса, называют экземплярами этого класса. Можно создать иерархию классов с классом-родителем и несколькими классами-потомками. Основой для этого являются производные классы.

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

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

Виртуальные функции. Виртуальные функции определяются в родительском классе, а в производных классах происходит доопределение этих функций и для них создаются новые реализации. При работе с виртуальными функциями сообщения передаются как указатели, которые указывают на объект вместо прямой передачи объекту. Виртуальные функции используют таблицу для адресной информации. Эта таблица инициализируется во время выполнения при помощи конструктора. Конструктор вызывается каждый раз, когда создается объект его класса. Задача конструктора в данном случае состоит в связывании виртуальной функции с таблицей адресной информации. Во время компиляции адрес виртуальной функции неизвестен; вместо этого ей отводится позиция в таблице адресов.

ООП полностью принадлежит к миру С++, поскольку в С нет основного ядра– абстрактного типа данных class . Поэтому переписать процедурно-ориентированную программу как объектно-ориентированную гораздо сложнее, чем просто подставить вместо одного ключевого слова другое.

ООП представляет собой технику программирования, которая позволяет рассматривать основные идеи как множество объектов. Используя объекты, можно представить задачи, которые необходимо выполнить, их взаимодействие и любые заданные условия, которые должны быть соблюдены. Структура данных часто образует основы объектов; таким образом в С или С++ тип struct может образовывать элементарный объект. Связь с объектом можно организовать при помощи сообщений. Использование сообщений похоже на вызов функций в процедурно-ориентированной программе. Когда объект получает сообщение, вступают в действие методы, содержащиеся в объекте. Методы (их иногда называют функциями — членами) аналогичны функциям процедурно-ориентированного программирования. Тем не менее метод является частью объекта, а не чем-то отдельным, как было бы в процедурном аналоге.

С++ -язык предметно-ориентированного программирования. Язык С++ поддерживает процедурную и объектно-ориентированную парадигмы программирования.

Объектно-ориентированное программирование – это новый способ подхода к программированию. Такое программирование, взяв лучшие черты структурного программирования, дополняет его новыми идеями, которые переводят в новое качество подход к созданию программ.

Наиболее важное понятие языков объектно-ориентированного программирования –это понятие объекта (object). Объект – это логическая единица, которая содержит данные и правила (методы) обработки этих данных. В языке С++ в качестве таких правил обработки выступают функции, т. е. объект в Borland C++ объединяет в себе данные и функции, обрабатывающие эти данные. Одним из самых главных понятий языка С++ является понятие класса. В языке С++ для того, чтобы определить объект, надо сначала определить его форму с помощью ключевого слова Ближайшей аналогией класса является структура. Память выделяется объекту только тогда, когда класс используется для его создания. Любой объект языка С++ имеет одинаковые атрибуты и функциональность с другими объектами того же класса. За создание своих классов и поведение объектов этих классов полную ответственность несет сам программист. Работая в некоторой среде, программист получает доступ к обширным библиотекам

стандартных классов. Обычно, объект находится в некотором уникальном состоянии, определяемом текущими значениями его атрибутов. Функциональность объектного класса определяется возможными операциями над экземпляром этого класса.

Структура-группа данных различных типов и(или) назначения, которые представляют собой единый информационный элемент.

struct Zmeja // структура змейка

int PCount; //количество яблок

Каждый элемент данных, называемый полем, имеет различное назначение. Одно поле содержит точки, другое количество яблок Однако все эти поля связаны между собой ,поскольку относятся к одному и тому же объекту «змейка» .

Поскольку в объектах также можно хранить группы разнотипных данных, то они тоже содержат структуры. Отличие структуры от класса в том, что в структуре нет закрытых и защищенных членов. Все члены структуры открыты.

Объявление структуры аналогично объявлению класса но вместо ключевого слова class ставится ключевое слово Struct :

Объявление данных или объектов

Объявлений структуры не подразумевает создание объекта или переменной. Объявление-это просто описание будущего объекта, в данном случае змейки. Чтобы использовать объект определенного класса или переменную определенного типа их сначала необходимо объявить в качестве объекта этого класса или переменной этого типа.

Аналогично для использования структурной переменной необходимо объявить переменную этой структуры.

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

Цель: Создать игру на ловкость “Змейка”

Законченный вариант игры змейка должен содержать:

1) “Змейку”, которая может двигаться в ограниченной плоскости. Маневрами “Змейки” должен управлять играющий. “Змейка” должна увеличиваться в размерах при столкновении с “яблоком” и погибать при столкновении с “стеной”, при пересечении самой себя и при выходе за границы плоскости заданной программистом.

2) “Яблоко” или другой объект, при столкновении с которым “Змейка” “съедает” его(увеличивается в длину в зависимости от условий заданных программистом.

3) “стена” объект при столкновении с которым змейка погибает.

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

4.Опиание алгоритма решения в псевдокоде (команды в виде текста на русском языке).

1) Описываются переменные и константы

2) Выбор начальных координат случайным образом

3) Прорисовка начального положения

4) Генерация на поле яблок случайным образом

5) Проверка: не появилось ли яблоко на черве.

6) Управление “Змейкой” с клавиатуры.

7) Проверка: “не укусила” ли “змейка сама себя”, если укусила выводится информационное окно (Информационная форма), в противном случае переходим к следующему пункту.

8) Проверка: “не съела” ли “змейка” “яблоко” если съела, то наращиваем ей хвост и переходим к пункту 3), в противном случае см. Следующий пункт.

9) Перерисовка “Змейки”

Игра на ловкость “Змейка”

Законченный вариант игры змейка должен содержать:

4) “Змейку”, которая может двигаться в ограниченной плоскости. Маневрами “Змейки” должен управлять играющий. “Змейка” должна увеличиваться в размерах при столкновении с “яблоком” и погибать при столкновении с “стеной”, при пересечении самой себя и при выходе за границы плоскости заданной программистом.

5) “Яблоко” или другой объект, при столкновении с которым “Змейка” “съедает” его(увеличивается в длину в зависимости от условий заданных программистом.

6) “стена” объект при столкновении с которым змейка погибает.

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

Функции управления экранными объектами.

H Змейка в 33 строки для Android на Java в черновиках

.collapse»>Содержание

Конечно, 33 строки — это «маркетинговый» ход для привлечения внимания.
Полное количество строк в основном и единственном классе равно 86, но ядро как раз столько и занимает (33). Внутри код змейки, самого маленького приложения для Android, комментарии и некоторые исследования на тему уменьшения размеров, сборка приложения из командной строки с использованием Proguard.

Быстрые ссылки по статье:
самое маленькое приложение;
змейка;
ссылки на github.

Введение

Думаю, что многие видели HelloWorld в Eclipse для Android.
Выглядит, особенно для новичка, весьма некомпактно. Тут очень много, назовём условно, «лишнего», для того чтобы разобраться, как это всё работает, что из чего следует, и как настраивать приложение.
От версии к версии иерархия файлов постоянно усложняется, что простоты к работе не добавляет.

1. две папки с Java-классами (src, gen). src содержит исходники, gen — сгенерированные классы. В основном, в папке gen бывает R.java.
2. Папка для библиотек libs. В случае HelloWorld создаётся библиотека android-support-v4.jar (или её более новая версия). Эта библиотека используется для обратной совместимости приложений.
То есть, если какие-то новые особенности (например объекты UI), создадут разработчики ОС, то, для того чтобы всё работало и на более ранних версиях, используются именно эти библиотеки. Также при помощи этой библиотеки разработчики исправляют некоторые ошибки. При использовании этой библиотеки, приложение, безусловно, значительно увеличит свой размер. Тут можно посмотреть список всех изменений по версиям.
3. ресурсная папка (res), в которой обычно располагаются изображения, настройки стилей, различные строки, и много другого прочего. Все файлы из этой папки получают уникальный ID в автоматически создаваемом при компиляции R.java-файле, который помещается в папку gen. ID можно (нужно) использовать внутри приложения, для того чтобы выделить тот или иной объект. Например, иконка для приложения.
4. asserts служит для хранения всех любых других видов файлов, которые нужно использовать в приложении, но им не будет выделен ID. Например, шрифт.
5. Файл-манифест приложения AndroidManifest.xml. Из него ОС узнаёт, что и как запускать, какие разрешения есть у приложения и т.п.
6. ic_launcher-web.png — файл-изображение для Google Play. Честно говоря, не знаю, насколько сейчас это является обязательным пунктом. В крайний раз, когда обновлял приложение на Google Play, этого не требовалось. Минутка субъективизма: не понимаю, что этот файл заслужил расположение в корне.
7. Текстовых файла для настроек проекта project.properties. Самый, пожалуй, частый вариант редактирования — включить/выключить использование proguard.
8. Текстовый файл для настроек proguard: proguard-project.txt

В принципе, для написания приложения достаточно только основной класс для Activity и AndroidManifest.xml

При помощи project.properties и proguard-project.txt можно настраивать работу Proguard. У него самая главная функция — сокращать имена по минимуму, что помогает усложнить реверс инжиниринг, а также сократить размер выходного файла. Имена переменных, методов и классов сокращаются до одно-, двухбуквенных.
Родная сборка приложения от Eclipse достаточно хороша, но лучше воспользоваться более «ручным» способом создания приложения при помощи командной строки. Как минимум исчезнет класс BuildConfig.java, который «ни с чего» появляется в папке gen. Также я заметил такую особенность, что родной компилятор собирает не только java, но и прочие файлы, которые находятся на одном уровне с исходниками. Чтобы не ошибиться(и не слить в релиз то, что не нужно), лучше воспользоваться компиляцией из командной строки.


Как это сделать, подробно написано в этой отличной статье.
Но при работе Тут bat-файл был переработан: добавлена корректная обработка путей в Windows, работа с Proguard, генерация ключа вынесена в отдельный батник.

Как работать с Proguard через командную строку.
Proguard работает с class-файлами (в нашем случае это файл из папки obj). Он всё собирает в выходной jar-файл (в нашем случае ./objPro/classes-processed.jar). Полученный jar-файл уже кормим сборщику apk-файлов. В итоге, всё собирается в dex-файлы, и apk-файлы. Для настройки сборки используется android.pro-файл. Если Proguard не используется, то всё собирается сразу из папки obj с помощью class-файлов.

Самое маленькое приложение на Android

android-support-v4.jar не используется. Ресурсы из папки res все удалены. В этом случае иконка приложения — это автопортрет Android, а строки (название приложения) записываются не ссылками на ресурсы, а в явном виде.

После сборки получается aSmall.apk — 2832 байта, aSmall.unsigned.apk — 945, что показывает, насколько много отъедает сертификат приложения. dex — 404 байта, classes-processed.jar — 248 байт. Это минимум.

Змейка

Github
В начале, конечно, захотелось мини-Excel, но я не нашёл хороший вариант в Java, при котором будет работать аналог функции exec в Javascript. Будет очень интересно посмотреть на результат, если кто-то сможет реализовать подобное.
Характеристики кода: полное количество строк A.java — 86, без import’ов — 69, «физика» поведения — 33 строки (что сравнимо с Javascript).
Приложение — полноэкранное. Управление при помощи жестов — вверх, вниз, влево, вправо.
Исходный код A.java.
A.java добавлен внутренний класс V extends View, который выводится на полный экран, в V есть в свою очередь свой внутренний класс P (Physics), который и описывает поведение змейки. Вот его размеры и равны примерно 30 строкам.

Алгоритм работы
приложение запускается в портретном режиме, основным элементом становится gv = new V();
В классе gv добавляется обработка жестов и запускается физику. В Физике инициализируется таймер (Timer), внутри которого происходит вычисление поведения змейки. Runnable и ASyncTask по размеру бы были гораздо больше. Сама змейки хранится в ArrayList. Были попытки сделать это через bitArray или через обычный массив, но в ArrayList всё как-то компактней получилось.

Как было сэкономлено место.

Экономия места в коде
1. Использование for, в параметрах которого записано несколько операций.
Пример:
было

2. ()?: вместо сложных if

3. инримент +±- совместно с if, — заменяет целые блоки switch-case

4. инициализация переменных в методах.
пример
было (1ая версия функции)

стало (2ая версия функции)

Уменьшения строк для пунктов 1-3 не дают уменьшения размера выходного apk, так как варианты «до» и «после» в jar-файле имеют примерно одинаковый код.

С пунктом 4 странно на получается странно. Если взять и протестировать использование функции summ в разных вариантах во всех трёх проектах (helloworld, small, snake), как изменяются размеры файлов при использовании в проекте этих методов, то получится следующая картина (цифры — количество байт):

Jar-файл уменьшается при использовании второй функции, а apk и dex увеличиваются. Скорее всего это связано с архивированием данных. Возможно, в некоторых случаях это даст свои результаты. Правда, они могут не оправдать Ваши ожидания.
На этом, пожалуй, всё.

Технология разработки визуальных кроссплатформенных приложений с использованием фреймворка Qt на примере программы “Snake”

В современном мире, очень важно поддерживать работу приложения на разнообразных платформах. Типичным примером является программное обеспечение, предназначенное для работы в операционных системах Linux и Windows одновременно. Qt — является отличным фреймворком, который позволяет создавать визуальные, кроссплатформенные приложения.

Актуальность кроссплатформенности в игровой индустрии успешно доказывает опыт американской компании Valve, получившая тотальную известность, выпустив крайне успешную и хорошо принятую критиками игру Half-Life.В настоящее время для разработчика крайне важно поддерживать множество операционных систем для работы приложения. Кроссплатформенность распространяется практически на каждую it-структуру, начиная от кроссплатформенных языков программирования, таких как c, c++, Pascal, заканчивая кроссплатформенными средами исполнения и пользовательскими интерфейсами. Всем известная OpenGL – открытая графическая библиотека, определяющая платформо-независимый программный интерфейс для написания приложений, использующих двумерную и трёхмерную компьютерную графику, которая также используется в данном проекте, наглядный пример успеха платформонезависимого продукта. Qt – кроссплатформенный инструментарий разработки ПО на языке программирования C++, именно он станет нашим главным «другом» на момент написания проекта, так и в дальнейшей перспективе разработки приложений. Из всего вышесказанного становится ясной актуальность кроссплатформенных приложений. Получение опыта разработки таких приложений и наглядное демонстрация всей «мощи» кроссплатформенного инструментария и составляет тему данной работы.

Объект исследования: одно из направлений программирования – кроссплатформенная разработка приложений.

Предмет исследования: практическое применение принципов разработки кроссплатформенных, визуальных приложений.

Цель: получение навыков и практического опыта разработки платформо-независимого, графического приложения с использованием фреймворка Qt .

Задачи:

  1. Изучить актуальность кроссплатформенных приложений.
  2. Разобраться с принципами работы фреймоврка Qt .
  3. Ознакомиться с графическим api OpenGL.
  4. Погрузиться в проектирование пользовательского интерфейса для приложения.
  5. Освоить основные принципы работы с языком запросов SQL,на примере работы с MySQL.
  6. Получить опыт работы с современным средством контроля версий Git, на примере работы с GitHub.
  7. «Поднять» и настроить сервер на FreeBSD.
  8. Разработать программный и пользовательский интерфейс программы.
  9. Создать дистрибутив данной программы и распространить его.

Используемое ПО

Фреймворк Qt

В процессе подготовки программы для демонстрации возможностей кроссплатформенного программирования и получения опыта программирования визуальных приложений, мы решили использовать фреймворк Qt .

Почему стоит использовать Qt?

Qt предоставляет программисту не только удобный набор библиотек классов, но и определённую модель разработки приложений, определённый каркас их структуры. Следование принципам и правилам «хорошего стиля программирования на C++/ Qt » существенно снижает частоту таких трудно отлавливаемых ошибок в приложениях как утечки памяти (memoryleaks), необработанные исключения, незакрытые файлы или неосвобождённые дескрипторы ресурсных объектов, чем нередко страдают программы, написанные «на голом C++» без использования библиотеки Qt .

У данного фреймворка имеется ряд преимуществ, из-за которых он и был выбран в качестве главного «наставника» в написании проекта.

Следует отменить несколько из них:

  1. Кроссплатформенный инструментарий разработки программного (далее – ПО) обеспечения на языке программирования C++.
  2. Несколько видов лицензии распространения ПО, в том числе и бесплатной.
  3. Использование MetaObjectCompiler(MOC) — предварительной системы обработки исходного кода (в общем-то, Qt — это библиотека не для чистого C++, а для его особого наречия, с которого и «переводит» MOC для последующей компиляции любым стандартным C++ компилятором).
  4. Поддержка множества языков программирования, таких как:
    1. C++
    2. PySide
    3. Python– Py Qt
    4. Ruby – Qt Ruby
    5. Java – Qt Jambi
    6. PHP –PHP- Qt
  5. Хорошо продуманный, логичный и стройный набор классов, предоставляющий программисту очень высокий уровень абстракции. Благодаря этому программистам, использующим Qt , приходится писать значительно меньше кода, чем это имеет место при использовании, например, библиотеки классов MFC. Сам же код выглядит стройнее и проще, логичнее и понятнее, чем аналогичный по функциональности код MFC или код, написанный с использованием «родного» для X11 тулкита Xt. Его легче поддерживать и развивать.

Знакомство с OpenGL

Так как мы будем разрабатывать платформо-независимую программу, наш выбор пал именно на OpenGL.

Данная графическая библиотека включает в себя более 250 функций для рисования сложных трёхмерных сцен из простых примитивов.

В основном используется при создании компьютерных игр, САПР (Система автоматизированного проектирования), виртуальной реальности, визуализации в научных исследованиях.

Стандарт OpenGL, с появлением новых технологий, позволяет отдельным производителям добавлять в библиотеку функциональность через механизм расширений. Расширения распространяются с помощью двух составляющих: заголовочный файл, в котором находятся прототипы новых функций и констант, а также драйвер устройства, поставляемого разработчиком. Каждый производитель имеет аббревиатуру, которая используется при именовании его новых функций и констант. Например, компания NVIDIA имеет аббревиатуру NV, которая используется при именовании её новых функций, как, например,glCombinerParameterfvNV(), а также констант, GL_NORMAL_MAP_NV. Может случиться так, что определённое расширение могут реализовать несколько производителей. В этом случае используется аббревиатура EXT. В случае же, когда расширение одобряется консорциумом ARB, оно приобретает аббревиатуру ARB и становится стандартным расширением. Обычно расширения, одобренные консорциумом, включаются в одну из следующих спецификаций OpenGL.

«Змейка»: создание и особенности реализации

В рамках проекта была разработана программа «Змейка» для демонстрации преимуществ кроссплатформенного фреймворка Qt и графической библиотеки OpenGL; я не ставил перед собой задачу написать программу, которая «взорвёт» рынок, главным было получить практический опыт разработки кроссплатформенных приложений и усовершенствовать свои навыки реального программирования.

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

Программный интерфейс включал в себя элегантный и переносимый код возможность поддержки, которого реализована с помощью GitHub’a.

В конечном итоге получился достаточно неплохой готовый продукт. Далее рассмотрим его более подробно.

Пользовательский интерфейс

При проектировании пользовательского интерфейса мы выделили несколько пунктов, которые должна содержать наша программа:

  • Настройки
  • Таблица рейтингов
  • Авторизация
  • Игра

Опираясь на данные пункты, мы сделали первичный интерфейс с помощью Qt Designer.

Программный интерфейс

В процессе разработки приложения удалось выделить несколько компонентов программы:

  • Главное окно
  • Окно настроек
  • Окно регистрации/авторизации
  • Виджет игры
  • Логирование
  • Настройки (управление файлом, структурой)
  • База данных
  • Логика игры

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

Git или система контроля версий

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

GitHub — самый крупный веб-сервис для хостинга IT-проектов и их совместной разработки.

Сервис абсолютно бесплатен для проектов с открытым исходным кодом (каким мы и являемся) и предоставляет им все возможности, а для частных проектов предлагаются различные платные тарифные планы.


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

Для более наглядной демонстрации возможностей github, прилагаю несколько иллюстраций.

Подготовка и настройка сервера на FreeBSD

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

Для начала мы выкупили виртуальный сервер у хостера firstvds, процесс оказался довольно не сложный, в связи с тем, что я имел опыт работы с данным хостером и «возведением» серверов/баз данных.

Для начала к «новоиспечённому» серверу нужно было как-то подключаться, для данной цели мы выбрали, PuTTY — свободно распространяемый клиент для различных протоколов удалённого доступа, включая SSH, который нам и был нужен.

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

После возведения MySQL сервера, нужно было настроить права доступа.

Как и любой толковый сисадмин, я решил ограничить подключения для всех пользователей кроме того, что был создан для подключения программно по ip.

Над именем пользователя для программы мы особо не задумывались, по этому, было решено назвать его «programm».

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

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

Для администрирования базы данных был выбран MySQL клиент – Navicat.

Так, как мы будем фиксировать рекорды пользователей, нам нужно их где-то хранить информацию о пользователях и их рекордах.

Для данной цели было решено создать 2 таблицы:

  • Account – Таблица содержащая информацию о пользователях
  • Record – Таблица содержащая информацию о достижениях пользователей

В таблице аккаунтов было решено хранить:

  • Id – Уникальный номер записи в таблице
  • Name – Уникальное имя аккаунта
  • Password – Пароль аккаунта (пароль из соображений безопасности хранятся в md5)

Прилагаю иллюстрацию структур таблиц:

Из данных иллюстраций ясно видна связь таблицы рекордов и таблицы аккаунтов.

Под «капотом» (интересные моменты кода программы)

1. Главное окно

Разберём самые интересные моменты кода основного окна.

Как было сказано раньше – Qt очень упрощает жизнь программисту, сейчас мы поймём почему.

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

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

В данном случае, мы используем «говорящие» названия объектов кнопок, это упрощает восприятие кода.

Разберём пример с кнопкой выхода.

В функции connect, мы передаём первый аргумент – объект, от которого ждём сигнал, далее объект, у которого вызывается слот.

Передаём объект – кнопку выхода, сигнал – нажатие на неё, объект у которого вызывается слот – текущее окно и наконец, сам слот – это закрытие приложения.

Как было сказано ранее, мы можем добавлять свои слоты.

Во втором случае так и сделано, мы ожиданием клик, от кнопки настроек, и вызываем слот (функцию) из текущего класса.

При этом мы должны объявить данный слот:

После объявления следует описать его.

Мы разобрались с сигналами и слотами.

Рассмотрим структуру класса главного окна:

В арсенале класса имеются:

  • Конструктор, принимающий в виде аргумента родительский виджет.
  • Деструктор.
  • Функция изменения размера окна, которая вызывается при любом изменении главного окна
  • Функция-слот opensettings, функция создания/вызова окна настроек.
  • Функция-слот openrecords, функция создания/вызова окна рекордов.
  • Функция-слот openregistration, функция создания/вызова окна регистрации/авторизации.
  • Функция-слот installsizepolice, функцияфиксации размеров окна на момент начала игры.

Разберём каждый элемент:

В данной функции, мы инициализируем систему взаимодействия с базой данных и устанавливаем подключения с сервером.

Далее, как мы и планировали, передаём информацию об объекте управления базой данных в виджет игры, для взаимодействия с очками.

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

Здесь всё проще, мы освобождаем память из-под объектов управления базой данных и графического оформления приложения.

  1. Функция изменения размера окна

Первая и успешно решённая проблема, с которой мы столкнулись: мы используем для движения змейки шаг в 10 пикселей, нам нужно ровное кол-во клеток в сетке:

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

Числа 103 и 22, это сдвиг от области главного окна к виджету игры.

  1. Функция создания/вызова окна настроек

Для начала мы инициализируем само окно (объект окна), заодно передадим ему настройки приложения.

Далее функция exec поставит фокус на данное окно и отобразит его.

После закрытие окна, управление опять передаётся в основное окно, и мы успешно устанавливаем фокус на виджет с игрой.

  1. Функция создания/вызова окна рекордов

Всё аналогично предыдущему случаю, мы создаём объект окна и передаём в качестве аргумента указатель на наш объект управления базой данных.

  1. Функция создания/вызова окна регистрации/авторизации


Инициализации объекта окна, передача настроек приложения и базы данных.

2. Настройки. Один из методов работы с конфигурационными файлами

Практически в каждом проекте, встает задача чтения/записи конфигурации. Не секрет, что существует большое количество уже готовых библиотек для решения этой задачи. Некоторые из-них просты, некоторые чуть сложнее в использовании. Если же проект разрабатывается с использованием Qt , думаю, нет смысла линковать дополнительную библиотеку, так как в Qt есть все средства для создания очень простого, гибкого и кроссплатформенного решения. Как раз о таком решении хочу рассказать вам в этом разделе.

Для начала обратимся к структуре нашего класса:

Перейдём непосредственно к описанию каждой функции

Для начала мы инициализируем объект класса QSettingsfsettings, передав ему имя файла с настройками и его формат.

QVariant QSettings::value ( const QString & key, const QVariant & defaultValue = QVariant() ) const

Возвращает значение для настройки key. Если настройка не существует, то возвращает значение по умолчанию defaultValue.

Если файл настроек содержит значения параметров, то они будут записаны в переменные, в противном случае, будут записанные те, которые мы указали как defaultValue.

  1. Установка режима отображения количества кадров в секунду

void Settings::setValue ( const QString & key, const QVariant & value )

Устанавливает значение настройки key в значение value. Если key уже существует, то предыдущее значение перезаписывается.

void QSettings::sync ()

Записывает любые несохранённые данные в постоянное хранилище и перезагружает любые настройки, которые были к тому времени изменены другим приложением.

  1. Установка режима проигрывания звуков

Выполняются аналогичные действия пункту 2.

  1. Установка режима отображения матрицы

Матрицу, про которую идёт речь, мы уже видели в предыдущем разделе в пункте «Функция изменения размера окна».

  1. Установка имени аккаунта

В данной функции происходит сохранение имени пользователя.

Следует заметить, что пароль сохраняется в зашифрованном виде (md5).

  1. Установка статуса авторизации

Данный параметр помогает нам понять, прошёл ли пользователь авторизацию.

  1. Получения статуса отображения количества кадров в секунду

Функция возвращает статус отображения fpsво время работы приложения.

  1. Получения статуса проигрывания звуков

На основе возвращённого ответа функции, мы можем сделать вывод, проигрывать ли звук.

  1. Получения статуса режима отображения матрицы

На основе возвращённого ответа функции, мы можем сделать вывод, нужно ли отображать матрицу/сетку во время работы приложения.

  1. Получения имени пользователя

Функция возвращает имя пользователя, которые мы можем использовать в дальнейших целях.

Функция возвращает зашифрованный пароль пользователя.

  1. Получения статуса авторизации пользователя

На основе возвращённого ответа функции, мы можем сделать вывод, имеет ли смысл дальнейших действий с аккаунтом пользователя.

Именно так выглядит работа простого механизма изнутри.

Иллюстрация конфигурационного файла:

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

3. Окно настроек

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

Со стороны пользователя все, кажется «лёгко», именно так оно и будет, если мы используем Qt .

Рассмотрим класс окна:

Именно правильный программный интерфейс и каноническая реализация даёт простой и понятный код.

Для начала нам нужно проинициализировать объект класса настроек. Далее мы установим на чекбоксы значения аргументов из настроек. После нажатие на кнопку «ОК» мы сохраняем настройки.

Всё просто. Мы сохраняем значения из чекбоксов в настройки.

Именно на данном примере явно видны преимущества использования Qt .

4. База Данных

Система управления базами данных (СУБД) — совокупность программных и лингвистических средств общего или специального назначения, обеспечивающих управление созданием и использованием баз данных.

Qt дает возможность создания платформо-независимых приложений для работы с базами данных, используя стандартные СУБД. Qt включает «родные» драйвера для Oracle, Microsoft SQL Server, Sybase Adaptive Server, IBM DB2, PostgreSQL, MySQL и ODBC-совместимых баз данных. Qt включает специфичные для баз данных виджеты, а также поддерживает расширение для работы с базами данных любых встроенных или отдельно написанных виджетов.

Работа с базами данных в Qt происходит на различных уровнях:

1.Слой драйверов — Включает классы QSqlDriver, QSqlDriverCreator, QSqlDriverCreatorBase, QSqlDriverPlugin и QSqlResult. Этот слой предоставляет низкоуровневый мост между определенными базами данных и слоем SQL API.

2.Слой SQL API — Этот слой предоставляет доступ к базам данных. Соединения устанавливаются с помощью класса QSqlDatabase. Взаимодействие с базой данных осуществляется с помощью класса QSqlQuery. В дополнение к классам QSqlDatabase и QSqlQuery слой SQL API опирается на классы QSqlError, QSqlField, QSqlIndex и QsqlRecord.

3.Слой пользовательского интерфейса — Этот слой связывает данные из базы данных с дата-ориентированнымивиджетами. Сюда входят такие классы, как QSqlQueryModel, QSqlTableModelи QSqlRelationalTableModel.


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

Для начала нам нужно создать структуру базы данных, которую мы будем возвращать.

Рассмотрим структуру СУБД:

Обратите внимание на переменные, в которых мы указываем данные для подключения к серверу.

Пояснение: Во время написание конкурсной работы было решено, не скрывать части данных для соблюдения безопасности работы сервера.

Заглянем под «капот» субд.

На данном этапе мы указываем, какой из драйверов использовать, в нашем случае QMYSQL.

Далее указываем данные для подключения к базе данных.

  1. Функция подключения к базе данных

Изначально мы вызываем функцию open, которая возвращает статус, успешно ли произведено подключение.

В случае неуспешного подключения, будет выведена причина неудачного подключения.

  1. Функция отключения от базы данных

В функции удаляется глобальное подключение объекта к базе данных. Далее закрывается подключение к базе данных.

  1. Функция создания аккаунта для пользователя (API)

Для начала нам нужно проверить, имеется ли уже такой аккаунт, если имеется, то прекратить регистрацию.

QsqlQuery — набор средств управления выражениями SQL и их выполнения.

Укажем базу данных, которую мы будем использовать, в нашем случае db.

Далее нам нужно создать запрос.

Данный запрос выполнит вставку в таблицу account запись с указанным именем и зашифрованным паролем.

Скорее всего, вы заметили, что в запросе мы не указали имя и пароль, а поставили:name и password. Данные выражения будут заменены на переменные, которые мы указываем ниже. Имя остаётся без изменения. Пароль преобразуется из нормального вида в md5.

Далее мы выполняем данный запрос, если запрос выполнен успешно, мы добавляем игрока в таблицу рекордов, в противном случае выдаём ошибку.

  1. Авторизация пользователя (API)

Данная функция возвращает true – в случае успешной авторизации, false–в противном случае.

Данная функция предоставляется в двух экземплярах, 1 для работы с зашифрованным паролем и 2 для работы с не зашифрованным паролем.

В функции мы создаём запрос и ищем пользователя, так, как мы указали явно вывести нам либо одну запись, либо ничего. Мы получим либо 1 запись, либо 0. Только в случае полного совпадения логина и пароля мы получим запись. Поэтому количество записей можно использовать, как возвращающееся значение.

  1. Установка кол-во набранных очков (API)

Данная функция, по имени пользователя, обновляет его количество набранных очков.

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

  1. Проверка на занятость аккаунта (API)

В данной функции, мы определяем, существует ли пользователь с данным именем.

  1. Получение уникального идентификатора пользователя по имени аккаунта (API)

Функция в случае успешного выполнения, возвращает уникальный идентификатор пользователя по его имени аккаунта.

  1. Получение имени аккаунта по уникальному идентификатору

В данной функции мы получаем имя аккаунта, по уникальному идентификатору.

  1. Получения записи из таблицы рекордов по уникальному идентификатору

Данная функция возвращает структуру, в которой содержится имя аккаунта и его рекорд. Все действия выполняются с помощью уникального идентификатора пользователя.

  1. Получения списка рекордов всех участников игры «Змейка» в порядке убывания (API)

Данная функция возвращает вектор структур записей о рекордах.

В запросе присутствует ключевое слово DESC, которое устанавливает порядок вывода (убывание/возрастание).

В данном разделе мы полностью рассмотрели СУБД программы. Ознакомились с основами языкаSQL, поняли принцип работы с бд в Qt . В следующих разделах мы будем активно использовать рассмотренную СУБД.

5. Таблица рекордов

Неотъемлемая часть спортивного интереса – это таблица рекордов. Практически ни одна игра не обходится без данной функции.

На настоящий момент программа была уже опробована несколькими людьми.

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

В цикле мы создаём новую запись в таблице и заполняем её данными из вектора.

6. Виджет игры «Змейка»

Данный виджет выполняет основную роль – рисования.

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

Для обновления виджета, мы будем использовать таймер, который после заданного интервала, будет вызывать функцию обновления.

Наш виджет унаследован от QGLWidget.

Укажем несколько особенностей используемого виджета:


QGLWidget так устроен, что при первой инициализации класса он автоматически вызывает методы в следующем порядке:

При запуске: initializeGL()->resizeGL()->paintGL()

При изменении размера окна: resizeGL()->paintGL()

updateGL() вызывает paintGL()

initializeGL — необходимо использовать для глобальных настрое построения изображения, которые нет необходимости указывать при построении кадра.

resizeGL — служит для построения размера окна. Если в ходе работы изменится размер окна, но не изменить область просмотра, то при увеличении размера можно наблюдать непредсказуемые явления.

paintGL — этот метод будет выстраивать каждый наш кадр для отображения.

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

Рассмотрим класс виджета:

Сейчас более подробно рассмотрим каждый из методов класса.

В первую очередь мы принимаем СУБД, далее создаём объект настроек приложения, устанавливаем интервал для случайных значений и двойную буферизацию (двойная буферизация позволяет более корректно заменять изображение, чтобы не происходили скачки на экране: PaintGL сразу картинку не рисует на экран, а заносит в буфер, а по запросу swapBuffers() заменяет текущее изображение на то, что появилось в буфере).

На следующем этапе мы устанавливаем таймера, первый таймер, для обновления виджета, а второй — для змейки.

В данной функции мы

Обнуляем кол-во набранных очков,

Создаём новый экземпляр змейки.

Устанавливаем границы поля.

Устанавливаем состояние игры.

И убираем логотип игры.

Устанавливаем фокус на нашу змейку

И запускаем таймер.

Так как змейка погибает, мы проигрываем звук поражения.

Устанавливаем состояние игры на false, при этом состояние о поражении переводим в true.

Только после данных действий, мы останавливаем таймер змейки и удаляем её экземпляр.

Дальше мы проверяем, авторизирован ли игрок, если да, то проверяем рекорд, если он превзошёл свой рекорд, то обновляем его и показываем поздравление.

  1. Изменение размера виджета (Event)

Данная функция вызывается при изменении размера окна, из-за которого меняется размер виджета.

На время изменения размера, мы устанавливаем режим матрицы проекции.

Далее загружаем матрицу.

Изменяем область вывода изображения.

Запоминаем новые размеры виджета.

Посылаем змейке запрос на изменение размера поля.

  1. Функция обработки нажатий клавиш (Event)

В данной функции мы перехватываем нажатие и выполняем нужное действие, в нашей программе мы изменяем направления движения главной змейки.

Также по нажатию клавиши Escape, игры завершается.

  1. Функция, возвращающая настройки программы

Функция возвращает указатель на настройки приложения.

  1. Функция инициализации настроек OpenGL

В данном методе мы устанавливаем чёрный цвет очистки экрана.

Функция возвращает состояние игры.

  1. Функция подсчёта кол-во кадров в секунду (FPS)

В данной функции мы высчитываем кол-во кадров. Мы смотрим если время в секундах сейчас больше, чем было в прошлый раз, что сохраняем значение кадров.

Если оно не изменялось, то увеличиваем кол-во кадров (секунда не прошла)

  1. Функция рисования интерфейса

Первым делом, выбираем цвет рисования, т.к. линия у нас должна быть белой, мы устанавливаем белый цвет.

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

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

Получим из настроек состояние отображения fps, если нужно выведем кол-во fps.

  1. Функция рисования сетки

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

При этом по горизонтали от низа мы делаем отступ интерфейса.

  1. Основная функция рисования paintGL (Event)

Для начала мы установим буфер глубины и буфер цвета.

Далее установим матрицу проекции и включим её.

Определим координатную систему с помощью glOrtho, в нашем случае начало координат будет в правом верхнем углу.


Проверяем, если состояние игры положительное, то рисуем змею и еду, в противном случае проверяем, нужно ли показывать логотип, если нет, то смотрим, погибла ли наша змейка, если да, то выведем, сколько очков мы набрали. Далее смотрим по настройкам, если есть указание рисовать матрицу, рисуем её, также поступаем и с подсчётом fps. В любом случае рисуем интерфейс.

  1. Функция действий змейки

В данной функции, происходит взаимодействие с самой змейкой, основное действие — это её движение.

Далее мы проверяем, не столкнулась ли змейка, ни с кем из своих звеньев.

Потом идёт проверка на, то, находится ли голова на клетке с едой, если да, то проигрываем музыку поедания фрукта и добавляем одно звено, если это был «Мега» фрукт, то вычисляем очки по специальной формуле.

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

7. Логика «Змейки»

В этой главе было решено объединить 2 класса, это класс, самой змейки и класс её звеньев.

Приступим к заключительной части категории «Под капотом».

Рассмотрим 2 класса:

В функции рисования, мы пробегаемся по массиву звеньев и рисуем каждое из них

В данном методе, мы смотрим, является ли данная еда «мега», если да, то устанавливаем зелёный цвет, для рисования.

Далее мы рисуем квадрат в пределах заданных координат.

  1. Установка размеров поля

В данной функции, мы устанавливаем данное значение для каждого звена и запоминаем его для себя.

Данная функция используется для прикрепления нового звена к змейке. Она использует алгоритм расчёта последней клетки, последнего звена и на её место ставит текущее (новое) звено. Также для него оно устанавливает идентичное направление.

  1. Изменение направления движения змейки

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

Далее используем очень хитрый алгоритм. Когда звено доходит до определённых координат оно меняет направление. Данная процедура повторяется для каждого звена.

Первым делом мы инициализируем музыку. Далее мы создаём «голову» звено и ставим ему направление движения.

  1. Автоматическое движение змейки

В данной процедуре мы получаем направление движение каждого звена и двигаем его в том же направление, из-а чего создаётся эффект движения змейки.

Данные функции участвуют в проверке столкновения, первая проверяет, не совпадают ли координаты головы и любого из звена, если совпадает, то сообщаем о столкновении.

Метод генерирует в случайной точке еду, по достижении пяти «простых» поеданий еды, генератор генерирует специальную «мега» еду, которая даёт больше очков.

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

Имеет место и проверка, не оказалась ли еда в звене или в том же самом месте.

  1. Проверка на столкновение с едой

Метод проверяет, не столкнулась ли голова с едой.

В данных методов вызывается метод play, который проигрывает музыку.

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

Похожий пример, мы уже разбирали, когда говорили о рисовании еды. В данном случае всё идентично.

Данные функции отвечают за передвижение звена, в них происходит изменение значения координат и проверка на выход за пределы поля.

  1. Изменение направления движения с учётом координат

Выполняется проверка, нужно ли изменить направление движения на текущих координатах.

  1. Проверка выхода за поля

Дистрибутив игры

В качестве ПО для создания дистрибутива был выбран SmartInstallMarker.

С помощью данной программы мы с лёгкость смогли создать полноценный дистрибутив игры.

Заключение

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

Литература

  1. Standard C++ Library reference URL: https://cplusplus.com/reference/ Время доступа: 19.01.14
  2. Qt Documentation URL: https://doc.qt.digia.com/ Время доступа: 20.01.14
  3. OpenGL 4 Reference URL: https://opengl.org/sdk/docs/man/ Время доступа: 20.01.14
  4. Koenig A. Accelerated C++.-2002
  5. Lafore R/ Object-Oriented Programming in C++.-2011

Рекомендуем прочитать:

4 Комментарии “ Технология разработки визуальных кроссплатформенных приложений с использованием фреймворка Qt на примере программы “Snake” ”

На раскрыта тема «кроссплатформенных приложений» указанная в заголовке. Все остальное (почти) туфта. Зачем упоминание про термины типа СУБД? Или это академическая статья включая тексты из википедии? ��
При чем тут FreeBSD вообще? Частный субъективный случай реализации задачи взаимосвязи игроков и только.

СУБД использовалось для примера работы с базой данных, статья писалась как научная работа в 10 классе

«Змейка» на OpenGL

«Змейка» на OpenGL


В файле и релиз и код. Прошу прощения что все писал на родном. Но кому надо разберется.

Вложения

Название: Разработка приложения, представляющего собой компьютерную игру «Змейка»
Раздел: Рефераты по информатике, программированию
Тип: курсовая работа Добавлен 23:02:50 03 сентября 2008 Похожие работы
Просмотров: 991 Комментариев: 16 Оценило: 4 человек Средний балл: 5 Оценка: неизвестно Скачать
Zmejka.rar (6.0 Кб, 569 просмотров)
26.02.2012, 23:35

Игра «Змейка» (не удается открыть файл включение: time.h)
При компиляции выдает ошибку:Не удается открыть файл включение: time.h: No such file or.

В среде Dev-C++ OpenGL выдает ошибку «Cannot find -lglut32»
при компиляции выдает ошибку cannot find -lglut32 Версия devа 5.4.2

При подключении opengl много ошибок «undefined reference»
скачал библиотеку glut с этого сайта(эту версию:Pre-compiled Win32 for Intel GLUT 3.7 DLLs for.

Нарисовать спираль по книге «OpenGL супер книга» Липчака
Друзья! Там есть листинг 3.2, рисующий спираль в пространстве (типа пружины; зелёную проужину на.

C# OpenGL вращение камеры «мышкой» вокруг трёхмерного объекта
Я в С# новичок и в OpenGL. Какой-то бы целостный пример для вращения мышкой камеры вокруг куба.

Разработка компьютерной игры «Змейка» (стр. 1 из 2)

Ни для кого не секрет, что видео игры прочно заняли свою позицию в современной индустрии развлечений. Существуют попытки выделить компьютерные игры как отдельную область искусства, наряду с театром, кино и т.п. Разработка игр может оказаться не только увлекательным, но и прибыльным делом, примеров этому предостаточно в истории. Первые примитивные компьютерные и видео игры были разработаны в 1950-х и 1960-х годах. Они работали на таких платформах, как осциллографы, университетские мейнфреймы и компьютеры EDSAC. Самой первой компьютерной игрой стал симулятор ракеты, созданный в 1942 году Томасом Голдсмитом Младшим (англ. Thomas T. Goldsmith Jr.) и Истл Рей Менном (англ. Estle Ray Mann). Позже, в 1952 году, появилась программа «OXO», имитирующая игру «крестики-нолики», созданная А.С. Дугласом как часть его докторской диссертации в Кембриджском Университете. Игра работала на большом университетском компьютере, известном как EDSAC (Electronic Delay Storage Automatic Calculator). В настоящее время, разработка игры — это многомиллионный процесс, в котором задействована целая команда разработчиков, сложные современные технологии и даже маркетинговые ходы.

Целью же моей курсовой работы будет разработка развивающей ловкость игры — «Змейка».

компьютерная игра pascal программа

1. Постановка задачи

В данной курсовой работе я ставлю перед собой следующие задачи:

1. В программе должно присутствовать меню, в котором можно просматривать данные о разработчике и игре, рекорды и непосредственно переход к самой игре.

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

3. Змейка должна собирать пищу (символы на экране, которые появляются случайно); при этом змейка должна «разбиваться» при столкновении с границей игрового поля и со своим «хвостом».

4. Должна присутствовать возможность сохранения результата в типизированный файл. И вывод результатов на экран при последующем запуске программы.

2. Выбор метода реализации задачи

Для реализации игры будет использован язык программирования Pascal. Данный язык является наиболее распространённым языком программирования среди студентов. Основное назначение этого языка — обучение программированию. Это было заложено в языке Паскаль создателем Никлаусом Виртом. Также благодаря американской корпорации Borland, вложившей в язык Паскаль новые идеи и принципы, язык стал мощным средством для создания программ, которые могут решить широкий круг проблем: от простых вычислительных задач до сложных исследовательских, использующих огромные объемы данных.

Во многих случаях стандартных возможностей ввода-вывода данных с помощью процедуры Read, Readln, Write, Writeln оказывается явно недостаточно для разработки диалоговых программ. Поэтому при написании своей программы я буду использовать модуль CRT. С помощью этой библиотеки можно определить факт нажатия какой-либо спец. клавиши.

3. Составление общего алгоритма

После того, как программа будет запущена, на экране появится главное меню. С главного меню можно перейти к меню «Справка», просмотреть таблицу рекордов и, при помощи вкладки «Играть», перейти непосредственно к выбору уровня сложности (их всего 3: «глист» — самый легкий, «змея» и самый сложный — «анаконда») и к самой игре. В меню «Справка» можно посмотреть данные о разработчике, а также правила игры.

Рис.3.1 — Общий алгоритм программы

После выбора уровня сложности мы переходим к игровому полю. Управление змейкой осуществляется при помощи клавиш управления курсором. После того как игра закончилась, на экран выводится сообщение об этом и, если игрок набрал результат выше чем 10 место в списке рейтинга, предлагается ввести свое имя для сохранения результата. Далее осуществляется переход в главное меню. Это продолжается до тех пор, пока не буде нажата кнопка «Выход».

4. Выделение функциональных частей

Программа будет состоять из следующих функциональных частей:

· Подпрограмма, которая рисует кнопки всех меню.

· Подпрограмма, которая обеспечивает вывод и работу меню 2-го уровня.

· Подпрограмма, отвечающая за изменение положения змейки.

· Подпрограмма, которая обеспечивает работу с меню «Справка»

· Подпрограмма, отвечающая за столкновение змейки.

· Подпрограмма, которая отвечает за сохранение результатов.

5. Обоснование алгоритмов отдельных функциональных частей

Цель этой подпрограммы заключается в том, чтобы рисовать кнопки меню, осуществляется это следующим образом: При вызове процедуры надо указывать ее фактические параметры, именно они указывают подпрограмме, в каком месте стоит нарисовать кнопку меню и каким цветом нужно рисовать. Само рисование организуется при помощи счетного цикла (For.: =. to. do) и процедуры GotoXY (x,y), которая переводит курсор в место на экране с координатами x и y.

Цель этой подпрограммы заключается в том, чтобы нарисовать и организовать работу меню 2-го уровня. Сначала рисуются рамка потом, при помощи процедуры Ramka, рисуются вкладки, а затем в этих вкладках вписываются названия кнопок. Работа с меню организуется при помощи цикла с постпроверкой условия (repeat … until), условного оператора if. then. else и

функции Readkey. Работает это по следующему принципу: функция readkey указывает какая клавиша была нажата, далее при помощи условного оператора

определяется какую из вкладок меню перерисовать другим цветом, если была нажата клавиша курсора «вниз», то нижний пункт меню перерисуется другим цветом, а тот что был раньше — станет невыделенным.

Эта процедура переформировывает массив, в котором содержатся координаты «частей» змейки, это осуществляется следующим образом: первому элементу массива присваиваются новые координаты, а всем остальным — координаты предыдущего элемента (x [3] получит значение x [2], а x [2] — x [1]).

Эта процедура обеспечивает работу с меню «Справка». В основе этой процедуры лежит считывание и вывод на экран типизированного файла.

Через эту процедуру программа проверяет, не столкнулась ли змейка с границей поля или сама с собой. Это осуществляется при помощи условного оператора if. then. else, который сверяет координаты головы змейки с координатами границ игрового поля и «хвоста змейки».

Эта процедура считывает с файлов данные о рекордах, составляет из них массив, элементами которого являются записи с 2 полями (Имя и Результат), если был набран результат выше 10 места в списке рейтинга, присваивает 10 элементу массива данные содержащие имя игрока и набранный результат. Далее сортирует этот массив методом прямого обмена и записывает отсортированный массив в файл.

6. Разработка тестовых примеров

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

1. После запуска игры на экране должно появиться главное меню со вкладками «Играть», «Рекорды», «Справка», «Выход».

2. Выбрав меню «Рекорды», на экране должна появиться таблица результатов такого формата: :

3. Выбрав меню «Справка», на экране появится меню справки со вкладками

«Правила игры», «Разработчик» и «Назад». выбирая каждую вкладку, на экране должна будет появиться соответствующая информация.

4. Выбрав меню «Играть», на экране появится меню выбора уровня сложности с 3 вариантами сложности «Глист», «Змея», «Анаконда». После выбора уровня сложности появится игровое поле и начнется игра. Справа от игрового поля будет находиться информация, отображающая набранный счет, длину змейки в знаках и тройка лидеров.

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

6. После того как пользователь введет имя и нажмет ENTER появится снова главное меню. Программа будет работать до тех пор, пока не будет выбрана вкладка меню «Выход».

7. Разработка программы

При написании программы я использовал модули Паскаля Crt.

Crt содержит константы, переменные и подпрограммы, предназначенные для работы с консолью. В отличие от стандартного ввода-вывода, когда он осуществляется через операционную систему, подпрограммы модуля работают с BIOS, и даже непосредственно с видеопамятью. При работе с этим модулем экран разбивается на отдельные строки, а каждая строка — на отдельные позиции, в каждую из которых можно поместить один символ. Таким образом, весь экран разбивается на отдельные неделимые прямоугольные элементы. Для каждого элемента можно задать цвет фона и цвет символа. Этот модуль применяется тогда, когда нужно задать определенные цвета фона и символов, размещать данные на экране при помощи перемещения курсора на определенные заданные позиции, удалять символы с экрана, создавать окна для помощи, узнавать текущие координаты курсора, задерживать выполнение программы.

Именно этими принципами я руководствовался при разработке меню и самого процесса игры.

Также в моей программе я использовал типизированные файлы. Так информация о разработчике хранится в файле под названием Avtor. pas, правила игры хранятся в файле Pravila. pas. Таблица рекордов хранится в файле Itog. txt. Для того чтобы работать с рекордами (сравнивать результаты и сортировать таблицу результатов) мне потребовалось отдельный файл в котором хранятся только рекорды (Rec. dat), и файл в котором хранятся имена пользователей (Imena. txt).

Интересные проекты: «змейка» для терминала, работающая на этапе компиляции

Реализация игры Змейка на светодиодной матрице

Автор: Сергей Безруков (aka Ser60) и Matthew Holcomb, sergeilb60@mail.ru
Опубликовано 08.06.2020
Создано при помощи КотоРед.

Хотел я было начать статью словами типа кто в детстве не играл в такую игру на компе. Однако, спохватившись, осознал, что в моём детстве таких игр не было, как и вообще персональных компьютеров, а нынешнее поколение играло или играет в несравненно более продвинутые электронные игры. Тем не менее, сделать самому такую игру для себя или в подарок может быть кому-то интересно. Помимо всего прочего, это неплохой обучающий проект.

Напомню кратко правила игры. На экране периодически появляются объекты в случайных позициях (мы их называем фрукты), которые “съедаются” змеёй, управляемой пользователем. Змея может двигаться только по вертикали или горизонтали и не допускается при движении выходить за пределы поля или пересекать тело змеи — в этих случаях игра будет закончена. При съедении фрукта длина тела змеи увеличивается и прибавляется некоторое количество очков к счёту. Цель игры — набрать как можно больше очков. Скорость движения змеи увеличивается в процессе игры и в начале её имеется возможность выбрать один из трёх уровней сложности.

В Интернете легко ищутся реализации этой игры для компьютеров или смартфонов с красивой графикой. Однако, начинающим сделать что-то подобное не просто. В нашем случае вся графика реализована на 8×8 монохромной светодиодной матрице с CA, где фрукты индицируются одной точкой. Это был первый микроконтроллерный проект моего студента Мэтта, и мы решили поделиться нашей реализацией с сообществом. Сразу отмечу, что алгоритм игры и вообще её прототип были заимствованы из одного проекта на Arduino [1]. Мы переделали его под другую элементную базу и индикаторы, включая их управление.

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

Для получения растра на матрице используется динамическая индикация, при которой в каждый момент времени высвечивается один столбец матрицы. Смена столбцов производится каждую миллисекунду, что соответствует частоте обновления всего дисплея 125гц. Иррегулярная разводка выводов дисплея на схеме сделана с целью упрощения геометрии печатной платы. Драйвер матрицы IC3 задаёт ток каждого светодиода в столбце, определяемым сопротивлением резистора R12. При питании от батарей пришлось пойти на компромисс между яркостью матрицы и потребляемым схемой током. Кстати, матрица содержит пару светодиодов для каждой точки – красный и зелёный. Нами используется только один из них – зелёный, поскольку чувствительность глаза к зелёному цвету выше чем к красному, что позволило несколько уменьшить ток через светодиоды. Загрузка данных в драйвер производится по интерфейсу SPI на частоте 400кгц. После загрузки данных для очередного столбца формируется краткий строб на входе LE (Latch Enable), в результате которого принятые данные передаются в каскад управления светодиодами. Это исключает мерцание светодиодов в процессе загрузки данных в драйвер. Активизация столбца матрицы выполнена на основе ключей Q1 – Q4, управляемых регистром сдвига IC2. При этом в начале каждого растра в регистр записывается идиница с пина 13 МК и нули для каждого из следующих 7 столбцов. Единица сдвигается регистром при переключении столбцов, что обеспечивает работу лишь с одним из них в каждый момент времени. Координатная система точек матрицы показана ниже. Матрица сканируется не в направлении увеличения или уменьшения х-координаты точек, а в некотором смешанном режиме, определяемом геометрией разводки соединений, что учтено в программе МК.

Загрузка данных в ЖК дисплей HG1 производится также по интерфейсу SPI, линии данных и тактирования которого объединены с драйвером матрицы IC3. В обоих случаях используестя только аппаратный SPI передатчик в МК, т.к. чтение данных из ЖК дисплея и драйвера матрицы не предполагается. Транзистор Q1 служит для включения подсветки ЖК дисплея. Однако, впоследствии для экономии энергии батарей было решено не использовать подсветку. Показания дисплея хорошо видны на свету и без неё.

Логика игры, интерактив с пользователем, и управление матрицей контролируется программой на языке С и микроконтроллером IC1 архитектуры ARM Cortex-M0+. Как отмечалось выше, реализация алгоритма игры с небольшой адаптацией была заимствована из проекта [1] для Arduino. Адаптацию можно было-бы реализовать более красиво в смысле кода, если-бы у Мэтта было больше времени. Использование ARM контроллера семейства Kinetis в проекте продиктовано тем, что он был выбран как стандарт в моём курсе в этом году. Микроконтроллер работает в режиме VLPR (Very Low-Power Run) и в активном режиме тактируется на частоте 4 мгц при частоте шины APB 800кгц. Этого вполне достаточно для реализации игры и его собственное потребление в таком режиме ничтожно по сравнению с остальной частью схемы и составляет около 250мкА.

Схема собрана на односторонней печатной плате, несколько неразведённых соединений реализованы проволочными перемычками. Питание схемы производится от четырёх батарей типоразмера АА с понижением напряжения до 3.3В высокоэффективным DC/DC преобразователем IC4 в стандартном включении. Применение четырёх батарей позволяет пользоваться игрой вплоть до их полного разряда. При этом минимальное напряжение на входе преобразователя не опускается ниже 4В, что необходимо для его нормальной работы. Батарейный отсек закреплён на пластине из оргстекла, установленной на стойках с тыльной стороны платы. К этой-же пластине приклеен выключатель питания ползункового типа.

Токопотребление схемы от батарей зависит от количества индицируемых на дисплее точек и в начале игры, когда тело змеи не длинное, варьируется около 40мА. В конце игры оно увеличивается раза в 1.5 — 2. Именно поэтому для уменьшения тока батарей использован понижающий преобразователь, а не повышающий при работе от одной-двух батарей. Исходный код программы и файл платы для Eagle прилагаются.

Мастер Йода рекомендует:  .NET — всё по этой теме для программистов
Добавить комментарий