Автор Анна Евкова
Преподаватель который помогает студентам и школьникам в учёбе.

Критерии выбора средств разработки мобильных приложений (Разработка требований к мобильным приложениям)

Содержание:

ВВЕДЕНИЕ

В современном мире, рынок разнообразных фреймворков, имеющих прямое отношение к мобильным устройствам, достаточно велик. Многие средства сливаются воедино, при этом имея разные технологические функции [2] Из всех существующих фреймворков можно вычеркнуть те, которые предназначены для разработки web-приложений, разнообразные enterprise-решения, средства прототипирования.

Создание приложений на мобильных устройствах развивается весьма активно, рынок мобильных приложений переполнен, разнообразен в разных сферах [1, 3, 5]. Большинство бизнесменов дают согласие на создание мобильных приложений для своего предприятия с целью совершенствования маркетинговой стратегии.

Язык программирования Java – это язык высокого уровня. Его можно назвать универсальным, так как его можно использовать для разных задач и платформ.

По версии TIOBE, в 2017 году Java стала языком программирования, обойдя в гонке С, С++ и ещё 17 языков-номинантов, и на сегодняшний день не теряет своей актуальности даже несмотря на то, что про Java-язык существует более 20 лет и успел обрасти мифами и домыслами.

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

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

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

По статистике, Java установлена на 97% процентах корпоративных компьютеров, около трех миллиардов телефонов имеют инструменты, написанные на Java.

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

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

Основное применение – серверная часть приложений, веб- и не очень веб-приложений, всякие корпоративные системы - что-то крупное, тяжеловесное.

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

Java наиболее популярна у web-разработчиков. Большинство приложений на страницах сайтов запускаются если на ПК есть оболочка для запуска Java. Популярность обусловлена тем, что написанные на этом языке веб-приложения отличаются стабильностью работы, высокой интерактивной функциональностью, быстродействием.

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

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

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

Java заточена под проектную разработку, Oracle, компания Sun при создании своих продуктов использовали именно ее. В этом направление они сделали очень многое, поэтому при выборе языка разработки крупных проектов выбор падет на Java.

Безопасность данных для одна из ключевых аспектов Java. Там есть настройки, которые позволяют заблокировать исполнение определенного кода. После выхода каждой версии Java, половина патчей для нее – это security-patch.

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

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

1. Описание задачи на исследование и проектирование

1.1 Формулировка и описание и задачи

Игра «Жизнь» была изобретена в 1970 году британским математиком Джоном Хортоном Конвеем [18]. Конвей проявил интерес к проблеме, которая была очевидна в 1940-х годах математиком Джоном фон Нейманом, который стремился найти гипотетическую машину, которая обладала способностью создавать копии себя и была бы успешной. Тогда он обнаружил математическую модель для такой машины с очень сложными правилами на прямоугольной сетке. Таким образом, «Игра жизнь» была способом упрощения идей фон Неймана. Это самый известный пример клеточного автомата, который представляет собой любую систему, в которой правила применяются к ячейкам и их соседям в регулярной сетке. Мартин Гарднер популяризировал «Игру жизнь», написав две статьи для своей колонки «Математические игры» в журнале Scientific American в 1970 и 1971 годах.

Игра представляет собой взаимодействие с «нулевым игроком», что означает, что ее эволюция определяется ее начальным состоянием, не требуя дальнейшего ввода. Игрок взаимодействует с Game of Life, создавая первоначальную конфигурацию и наблюдая за тем, как она развивается.

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

  • любая живая клетка с менее чем двумя живыми соседями умирает, причина – недостаточно потенциала для развития;
  • любая живая клетка с двумя или тремя живыми соседями живет в следующем поколении.
  • Любая живая клетка с более чем тремя живыми соседями умирает, причина – перенаселение.
  • Любая мертвая клетка с ровно тремя живыми соседями становится живой клеткой, причина – рождение от живых соседей.

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

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

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

В «Жизнь» происходит много разных типов паттернов, которые классифицируются по их поведению. Общие типы шаблонов включают: объекты, которые не меняются от одного поколения к другому; объекты, которые возвращаются в исходное состояние после конечного числа поколений; и объекты, которые двигают себя через всю сетку.

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

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

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

  1. Блок;
  2. Лодка;
  3. Буханка;
  4. Улей.

Рисунок 1 – Шаблоны состояний: блок, лодка, буханка и улей

Игра «Жизнь» родилась из исследований Клода Шеннона и Джона Маккарти. Книга, в которую входит эссе о машинах Тьюринга, пробудила в Конвее увлечение механизмами, способными к спонтанному движению. И в то время, как другие энтузиасты автоматизации в шестидесятых мечтали собрать самореплицирующие машины, которые бы колонизировали Марс, Конвей стремился к фундаментальной простоте. Фактически, игра «Жизнь» началась как попытка упростить двумерную автоматическую машину Джона фон Неймана - абстракцию, в которой квадрат мог быть в одном из 29 возможных состояний. Однако определяющим состоянием квадрата были состояния окружающих четырех квадратов, которые также находились в любом из 29 состояний. Таким образом, машина допускала для разных конфигураций 20,155,149 (29 ^ 5), что делало ее в глазах Конвея «чрезмерно сложной». Вместо этого он представлял собой одномерную универсальную машину.

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

1.2 Разработка требований к мобильным приложениям

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

Требования к функциональности:

  1. приложение должно позволять задавать начальное состояние;
  2. приложение должно позволять менять параметры системы (размер поля);
  3. приложение должно позволять сохранять состояние системы;
  4. приложение должно позволять загружать ранее сохраненное состояние системы;
  5. приложение должно позволять “вмешиваться” в симуляцию системы, добавляя или удаляя клетки (расширение исходных правил);
  6. приложение должно позволять задавать скорость развития системы.

Требования к использованию:

  1. приложение должно быть выполнено в виде интуитивно понятного интерфейса;
  2. приложение должно выполнять все предъявленные требования к функциональности;
  3. приложение должно позволять использовать мышь для взаимодействия.

Требования к надежности:

  • приложение должно работать при любых стандартных обстоятельствах;
  • исключительные ситуации должны быть обработаны по мере возможности;
  • приложение должно быть отлажено и протестировано.

Требования к производительности:

  1. специальных требований к приложению не предъявляется;
  2. операционная система должна обладать минимальных набором характеристик для воспроизведения приложения.

Требования к поддерживаемости:

  1. приложение требует для своей работы специализированную программу (JRE);
  2. приложение должно быть кроссплатформенным;

Дополнительные требования:

  • программный код приложения должен быть оптимизирован;
  • программный код приложения должен содержать комментарии.

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

Проектирование программного продукта

Приложение состоит из трех основных компонентов (классов):

  1. симуляция игры (программная логика);
  2. отображение визуальных компонентов (кнопки, надписи и пр.);
  3. прорисовка системы на интерфейс (графический интерфейс).

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

Унифицированный язык моделирования (UML) может помочь моделировать системы различными способами. Одним из наиболее популярных типов в UML является диаграмма классов. Популярный среди разработчиков программного обеспечения для документирования архитектуры программного обеспечения, диаграммы классов – это тип структурной диаграммы, поскольку они описывают, что должно присутствовать в моделируемой системе.

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

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

Диаграмма классов:

Рисунок 2. UML-диаграмма классов

Как можно видеть из диаграммы классов (рис. 2.), за симуляцию отвечает класс SimulationOfLife, за отображение симуляции класс DrawingLifePanel, за общую прорисовку MainGUI.

2. Реализация программного продукта

2.1 Используемые библиотеки

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

Библиотека классов выполняет три задачи в рамках платформы Java:

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

В приложении активно используется библиотека Swing. Swing – это набор инструментов для виджета GUI для Java. Он является частью Java-классов Oracle (JFC) - API для предоставления графического интерфейса пользователя (GUI) для Java-программ.

Swing был разработан для обеспечения более сложного набора графических компонентов, чем предыдущий абстрактный набор инструментов (AWT). Swing обеспечивает внешний вид, который эмулирует внешний вид нескольких платформ, а также поддерживает привлекательный внешний вид, который позволяет приложениям выглядеть и чувствовать себя несвязанными с базовой платформой. Он имеет более мощные и гибкие компоненты, чем AWT. В дополнение к знакомым компонентам, таким как кнопки, флажки и метки, Swing предоставляет несколько дополнительных компонентов, таких как панель с вкладками, полосы прокрутки, деревья, таблицы и списки.

В отличие от компонентов AWT компоненты Swing не реализуются с помощью кода, специфичного для платформы. Вместо этого они полностью написаны на Java и поэтому не зависят от платформы.

Все последующие библиотеки необходимы в трех случаях;

  • программная логика;
  • графическая визуализация;
  • вспомогательные функции.

В приложении используются следующие библиотеки:

  1. java.awt.Color – для задания цветовой гаммы клеткам;
  2. java.awt.Dimension – для задания размерности клеткам;
  3. java.awt.Graphics – для прорисовки клеток;
  4. java.awt.Insets – для внутренних отступов элементов GUI;
  5. java.awt.Toolkit – для вспомогательных действий;
  6. java.awt.event.MouseAdapter – для реализации работы мыши;
  7. java.awt.event.MouseEvent – для обработки событий мыши;
  8. java.util.Random – для генерации псевдослучайных чисел;
  9. javax.swing.JPanel – для создания панели симуляции;
  10. java.awt.* – все библиотеки компонента awt для работы с фреймом;
  11. importjava.awt.event.* – все библиотеки компонента awt.ewent для обработки событий на фрейме;
  12. importjava.awt.image.BufferedImage – для сохранения изображения текущей симуляции;
  13. java.io.File – для файловой работы.
  14. java.io.FileReader – для загрузки состояния симуляции;
  15. java.io.FileWriter – для сохранения текущей симуляции;
  16. java.io.IOException – для обработки исключительных ситуаций;
  17. java.util.Scanner – для консольного ввода;
  18. javax.imageio.ImageIO – для общей работы с изображениями;
  19. javax.swing.* – дополнительные библиотеки для GUI;
  20. javax.swing.event.* – дополнительные библиотеки для GUI;
  21. java.util.Arrays – для использования безразмерного массива.

2.2 Описание модели приложения

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

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

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

  1. последовательно определим новые состояния для клеток, которые не касаются границ поля;
  2. последовательно определим новые состояния для клеток, которые соприкасаются с границами поля;
  3. применим новые состояния, отобразив их на основной доске.

Новое состояние для клетки рассчитывается следующим образом:

  1. Если клетка мертва:
    1. Если живых соседей ровно три – оживить, иначе оставить мертвой;
  2. Если клетка жива:
    1. Если живых соседей два или три – оставить жить, иначе убить.

Программный код итерации приведен на рисунке 3.:

/**

* Итерациясимуляции

*/

publicvoid iterate() {

// обрабатываемклетки, некасающиесякраевполя

for (inty = 1; y<height - 1; y++) {

for (intx = 1; x<width - 1; x++) {

intj = y * width + x;

byten = countNeighbors(j);

sideBoard[j] = iterateCell(masterBoard[j], n);

}

}

// обрабатываемграничныеклетки

// верхняя и нижняястроки

for (intx = 0; x<width; x++) {

intj = width * (height - 1);

byten = countBorderNeighbors(x, 0);

sideBoard[x] = iterateCell(masterBoard[x], n);

n = countBorderNeighbors(x, height - 1);

sideBoard[x + j] = iterateCell(masterBoard[x + j], n);

}

// крайниелевыйиправыйстолбцы

for (inty = 1; y<height - 1; y++) {

intj = width * y;

byten = countBorderNeighbors(0, y);

sideBoard[j] = iterateCell(masterBoard[j], n);

n = countBorderNeighbors(width - 1, y);

sideBoard[j + width - 1] = iterateCell(masterBoard[j + width - 1], n);

}

// обмениваемполяместами

byte[] t = masterBoard;

masterBoard = sideBoard;

sideBoard = t;

}

Рисунок 3. Программный код итерации

Приведем программный код решения о новом состоянии клетки (рис. 4.):

/**

* Симуляциядляоднойклетки.

*

* @param self собственноесостояниеклетки: 0/1

* @param neighbors кол-вососедей

* @returnновоесостояниеклетки: 0/1

*/

privatebyte iterateCell(byteself, byteneighbors) {

return (byte) (self == 0 ? (neighbors == 3 ? 1 : 0) : neighbors == 2 || neighbors == 3 ? 1 : 0);

}

Рисунок 4. программный код решения о новом состоянии клетки

Приведем программный код подсчета соседей (рис. 5.):

/**

* Подсчетсоседей, которыенекасаютсякраевклеток.

*

* @param j смещениеклетки в массиве

* @returnкол-вососедей

*/

privatebyte countNeighbors(intj) {

byten = 0;

for (inti = 0; i< 8; i++) {

n += masterBoard[j + neighborOffsets[i]];

}

returnn;

}

/**

* Подсчетсоседейдляграничныхклеток.

*

*/

privatebyte countBorderNeighbors(intx, inty) {

byten = 0;

for (inti = 0; i< 8; i++) {

intbx = (x + neighborXYOffsets[i][0] + width) % width;

intby = (y + neighborXYOffsets[i][1] + height) % height;

n += masterBoard[by * width + bx];

}

returnn;

}

Рисунок 5. Программный код подсчета соседей

2.3. Описание панели приложения

Панель представляет собой область, на которой располагается прорисовки симуляции. Соответственно, панель предназначена для отображения системы (игры «Жизнь»).

У панели следующие характеристики:

  • задержка между перерисовыванием;
  • размер клетки;
  • толщина границы клетки;
  • цвет живой клетки;
  • цвет мертвой клетки.

Приведем программный код прорисовки панели (рис. 6.). Выполняется следующий алгоритм:

  1. Базовая прорисовка компонента;
  2. Перебор всех клеток в симуляции:
  3. Если клетка жива – присвоить ей случайный цвет, иначе присвоить ей пустой цвет.
  4. Прорисовать границу для клетки заданной толщины.

/**

* Прорисовкасодержимогопанели.

*/

@Overrideprotectedvoid paintComponent(Graphics g) {

if (life != null) {

synchronized (life) {

super.paintComponent(g);

Insets b = getInsets();

Random rand = new Random();

for (inty = 0; y<life.getHeight(); y++) {

for (intx = 0; x<life.getWidth(); x++) {

bytec = life.getCell(x, y);

//g.setColor(c == 1 ? colorLive : colorEmpty);

g.setColor(c == 1 ? new Color(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256)) : colorEmpty);

g.fillRect(b.left + cellBorder + x * (cellSize + cellBorder), b.top + cellBorder + y

* (cellSize + cellBorder), cellSize, cellSize);

}

}

}

}

}

Рисунок 6. Программный код прорисовки панели

Примерпанелисзаданнымсостоянием (рис. 7.):

Рисунок 7. Панель приложения

2.4. Описание формы приложения

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

  • панель для прорисовки симуляции;
  • слайдеры для изменения размера и скорости обновления;
  • кнопки загрузки/сохранения симуляции;
  • кнопка очистки поля;
  • кнопка запуска симуляции.

Панель с компонентами (рис. 8.):

Рисунок 8. Настраиваемые параметры приложения

Полный вид формы по время симуляции (рис. 9.):

Рисунок 9. Работающее приложение

3. Тестирование

3.1. Разработка плана тестирования

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

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

3.2. Тестирования приложение

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

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

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

3.3. Развертывание приложения

Приложение не требует дополнительных условий для развертывания. Обязательным условием для запуска является наличие JRE (специализированной программы, которое позволяет запускаться Java-программам).

ЗАКЛЮЧЕНИЕ

В современном мире, рынок разнообразных фреймворков, имеющих прямое отношение к мобильным устройствам, достаточно велик. Многие средства сливаются воедино, при этом имея разные технологические функции [2] Из всех существующих фреймворков можно вычеркнуть те, которые предназначены для разработки web-приложений, разнообразные enterprise-решения, средства прототипирования.

Создание приложений на мобильных устройствах развивается весьма активно, рынок мобильных приложений переполнен, разнообразен в разных сферах [1, 3, 5]. Большинство бизнесменов дают согласие на создание мобильных приложений для своего предприятия с целью совершенствования маркетинговой стратегии.

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

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

СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ

  1. Илюшечкин, В.М. Основы использования и проектирования баз данных: Учебник для академического бакалавриата / В.М. Илюшечкин. – Люберцы: Юрайт, 2016. – 213 c.
  2. Minakov V.F., Ilyina O.P., Lobanov O.S. Concept of the Cloud Information Space of Regional Government // Middle-East Journal of Scientific Research. – 2014. – № 21 (1). – P. 190-196
  3. Барабанова М.И., Воробьев В.П., Минаков В.Ф. Экономико-математическая модель динамики дохода отрасли связи России // Известия Санкт-Петербургского государственного экономического университета. – 2013. – № 4 (82). – С. 24–28.
  4. Венделева, М.А. Информационные технологии в управлении.: Учебное пособие для бакалавров / М.А. Венделева, Ю.В. Вертакова. – Люберцы: Юрайт, 2016. – 462 c.
  5. Гаврилов, М.В. Информатика и информационные технологии: Учебник для прикладного бакалавриата / М.В. Гаврилов, В.А. Климов. – Люберцы: Юрайт, 2016. – 383 c.
  6. Дарков, А.В. Информационные технологии: теоретические основы: Учебное пособие / А.В. Дарков, Н.Н. Шапошников. – СПб.: Лань, 2016. – 448 c.
  7. Згадзай, О.Э. Информационные технологии в юридической деятельности: Учебное пособие / О.Э. Згадзай и др. – М.: ЮНИТИ, 2016. – 335 c.
  8. Коноплева, И.А. Информационные технологии. / И.А. Коноплева, О.А. Хохлова, А.В. Денисов. – М.: Проспект, 2015. – 328 c.
  9. Корнеев, И.К. Информационные технологии в работе с документами: Учебник / И.К. Корнеев. – М.: Проспект, 2015. – 304 c.
  10. Макарчук Т.А., Минаков В.Ф., Щугорева В.А. Облачные решения построения информационных систем управления ресурсами организации // Международный научно-исследовательский журнал = Research Journal of International Studies. – 2014. – № 1-1 (20). – С. 68-69.
  11. Минаков В.Ф., Минакова Т.Е. Информационное общество и проблемы прикладной информатики // Международный научно-исследовательский журнал = Research Journal of International Studies. – 2014. – № 1-1 (20). – С. 69-70.
  12. Саати Т. Принятие решений. Метод анализа иерархий. М.: Радио и связь. – 1993. – 278 с.
  13. Савитч, Уолтер. Язык Java. Курс программирования / Уолтер Савитч. – М.: Вильямс, 2015. – 928 c.
  14. Хабибуллин, Ильдар. Самоучитель Java / Ильдар Хабибуллин. – М.: БХВ-Петербург, 2014. – 768 c.
  15. Шилдт, Герберт. Java 8. Руководство для начинающих / Герберт Шилдт. – М.: Вильямс, 2015. – 720 c.
  16. Эккель, Брюс. Философия Java / Брюс Эккель. – М.: Питер, 2016. – 809 c.

ПРИЛОЖЕНИЯ

Приложение 1

Диаграмма классов

Приложение 2

Полный программный код с комментариями

package Game;

import java.util.Arrays;

publicclass SimulationOfLife {

/**

* Главнаядоска

*/

privatebyte[] masterBoard = null;

/**

* Доскадляперерисовывания

*/

privatebyte[] sideBoard = null;

/**

* Ширинаивысотадоски

*/

privateint width, height;

/**

* Направлениядляпоискаграничныхсоседей

*/

privateint[] neighborOffsets = null;

/**

* Направлениядляпоискасоседей

*/

privateint[][] neighborXYOffsets = null;

/**

* Конструктор

*

* @param width Ширина

* @param height Высота

*/

public SimulationOfLife(intwidth, intheight) {

this.width = width;

this.height = height;

masterBoard = newbyte[width * height];

sideBoard = newbyte[width * height];

neighborOffsets = newint[] {-width - 1, -width, -width + 1, -1, 1, width - 1, width, width + 1};

neighborXYOffsets = newint[][] { {-1, -1}, {0, -1}, {1, -1}, {-1, 0}, {1, 0}, {-1, 1}, {0, 1}, {1, 1}};

}

/**

* Получитьширину

*/

publicint getWidth() {

returnwidth;

}

/**

* Получитьвысоту

*/

publicint getHeight() {

returnheight;

}

/**

* Очиститьдоску

*/

publicvoid clear() {

Arrays.fill(masterBoard, (byte) 0);

}

/**

* Получитьзаданнуюклетку

*/

publicbyte getCell(intx, inty) {

returnmasterBoard[y * width + x];

}

/**

* Задатьвыбраннуюклетку

*/

publicvoid setCell(intx, inty, bytevalue) {

masterBoard[y * width + x] = value;

}

/**

* Итерациясимуляции

*/

publicvoid iterate() {

// обрабатываемклетки, некасающиесякраевполя

for (inty = 1; y<height - 1; y++) {

for (intx = 1; x<width - 1; x++) {

intj = y * width + x;

byten = countNeighbors(j);

sideBoard[j] = iterateCell(masterBoard[j], n);

}

}

// обрабатываемграничныеклетки

// верхняя и нижняястроки

for (intx = 0; x<width; x++) {

intj = width * (height - 1);

byten = countBorderNeighbors(x, 0);

sideBoard[x] = iterateCell(masterBoard[x], n);

n = countBorderNeighbors(x, height - 1);

sideBoard[x + j] = iterateCell(masterBoard[x + j], n);

}

// крайниелевыйиправыйстолбцы

for (inty = 1; y<height - 1; y++) {

intj = width * y;

byten = countBorderNeighbors(0, y);

sideBoard[j] = iterateCell(masterBoard[j], n);

n = countBorderNeighbors(width - 1, y);

sideBoard[j + width - 1] = iterateCell(masterBoard[j + width - 1], n);

}

// обмениваемполяместами

byte[] t = masterBoard;

masterBoard = sideBoard;

sideBoard = t;

}

/**

* Подсчетсоседей, которыенекасаютсякраевклеток.

*

* @param j смещениеклетки в массиве

* @returnкол-вососедей

*/

privatebyte countNeighbors(intj) {

byten = 0;

for (inti = 0; i< 8; i++) {

n += masterBoard[j + neighborOffsets[i]];

}

returnn;

}

/**

* Подсчетсоседейдляграничныхклеток.

*

*/

privatebyte countBorderNeighbors(intx, inty) {

byten = 0;

for (inti = 0; i< 8; i++) {

intbx = (x + neighborXYOffsets[i][0] + width) % width;

intby = (y + neighborXYOffsets[i][1] + height) % height;

n += masterBoard[by * width + bx];

}

returnn;

}

/**

* Симуляциядляоднойклетки.

*

* @param self собственноесостояниеклетки: 0/1

* @param neighbors кол-вососедей

* @returnновоесостояниеклетки: 0/1

*/

privatebyte iterateCell(byteself, byteneighbors) {

return (byte) (self == 0 ? (neighbors == 3 ? 1 : 0) : neighbors == 2 || neighbors == 3 ? 1 : 0);

}

}

package Game;

import java.awt.Color;

import java.awt.Dimension;

import java.awt.Graphics;

import java.awt.Insets;

import java.awt.Toolkit;

import java.awt.event.MouseAdapter;

import java.awt.event.MouseEvent;

import java.util.Random;

import javax.swing.JPanel;

/**

* Панель для воспроизведения симуляции.

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

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

*/

public class DrawingLifePanel extends JPanel implements Runnable {

/**

* Скоростьсимуляциипоумолчанию

*/

private static final int DEFAULT_UPDATE_DRAW = 36;

/**

* Размер клетки на панели по умолчанию

*/

private static final int DEFAULT_CELL_SIZE = 18;

/**

* Размер толщины стенки клетки по умолчанию

*/

private static final int DEFAULT_CELL_BORDER = 1;

/**

* Цвет пустой клетки по умолчанию

*/

private static final int DEFAULT_CELL_EMPTY = 0x505050;

/**

* Цвет живой клетки по умолчанию

*/

private static final int DEFAULT_CELL_LIVE = 0xFFFFFF;

/**

* Потоксимуляции

*/

private Thread simThread = null;

/**

* Модельсимуляции

*/

private SimulationOfLife life = null;

/**

* Задержка в мс между шагами симуляции

*/

private int updateForDraw = DEFAULT_UPDATE_DRAW;

/**

* Размерклеткинаэкране

*/

private int cellSize = DEFAULT_CELL_SIZE;

/**

* Промежутокмеждуклетками

*/

private int cellBorder = DEFAULT_CELL_BORDER;

/**

* Цветмертвойклетки

*/

private static final Color colorEmpty = new Color(DEFAULT_CELL_EMPTY);

/**

* Конструктор

*/

public DrawingLifePanel() {

setBackground(Color.BLACK);

// редакторполя

MouseAdapter ma = new MouseAdapter() {

private boolean pressedLeft = false; // нажаталеваякнопкамыши

private boolean pressedRight = false; // нажатаправаякнопкамыши

@Override public void mouseDragged(MouseEvent e) {

setCell(e);

}

@Override public void mousePressed(MouseEvent e) {

if (e.getButton() == MouseEvent.BUTTON1) {

pressedLeft = true;

pressedRight = false;

setCell(e);

} else if (e.getButton() == MouseEvent.BUTTON3) {

pressedLeft = false;

pressedRight = true;

setCell(e);

}

}

@Override public void mouseReleased(MouseEvent e) {

if (e.getButton() == MouseEvent.BUTTON1) {

pressedLeft = false;

} else if (e.getButton() == MouseEvent.BUTTON3) {

pressedRight = false;

}

}

/**

* Устанавливает/стирает клетку.

*

*/

private void setCell(MouseEvent e) {

if (life != null) {

synchronized (life) {

// рассчитываем координаты клетки, на которую указывает курсор мыши

int x = e.getX() / (cellSize + cellBorder);

int y = e.getY() / (cellSize + cellBorder);

if (x >= 0 && y >= 0 && x < life.getWidth() && y < life.getHeight()) {

if (pressedLeft == true) {

life.setCell(x, y, (byte) 1);

repaint();

}

if (pressedRight == true) {

life.setCell(x, y, (byte) 0);

repaint();

}

}

}

}

}

};

addMouseListener(ma);

addMouseMotionListener(ma);

}

/**

* Получитьмодельсимуляции

*/

public SimulationOfLife getLifeModel() {

return life;

}

/**

* Инициализациямодели

*/

public void initialize(int width, int height) {

life = new SimulationOfLife(width, height);

}

/**

* Установказадержкискоростисимуляции

*/

public void setUpdateDelay(int updateForDraw) {

this.updateForDraw = updateForDraw;

}

/**

* Установкаразмераклеток

*/

public void setCellSize(int cellSize) {

this.cellSize = cellSize;

repaint();

this.setSize(getPreferredSize());

}

/**

* Запусксимуляции

*/

public void startSimulation() {

if (simThread == null) {

simThread = new Thread(this);

simThread.start();

}

}

/**

* Остановкасимуляции

*/

public void stopSimulation() {

simThread = null;

}

/**

* Проверка воспроизведения симуляции

*/

public boolean isSimulating() {

return simThread != null;

}

@Override public void run() {

repaint();

while (simThread != null) {

try {

Thread.sleep(updateForDraw);

} catch (InterruptedException e) {}

// синхронизация используется для того, чтобы метод paintComponent не выводил на экран

// содержимое поля, которое в данный момент меняется

synchronized (life) {

life.iterate();

}

repaint();

}

repaint();

}

/**

* Возвращает размер панели с учетом размера поля и клеток.

*/

@Override public Dimension getPreferredSize() {

Dimension sSize = Toolkit.getDefaultToolkit ().getScreenSize ();Toolkit.getDefaultToolkit ().getScreenSize ();

return sSize;

}

/**

* Прорисовка содержимого панели.

*/

@Override protected void paintComponent(Graphics g) {

if (life != null) {

synchronized (life) {

super.paintComponent(g);

Insets b = getInsets();

Random rand = new Random();

for (int y = 0; y < life.getHeight(); y++) {

for (int x = 0; x < life.getWidth(); x++) {

byte c = life.getCell(x, y);

//g.setColor(c == 1 ? colorLive : colorEmpty);

g.setColor(c == 1 ? new Color(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256)) : colorEmpty);

g.fillRect(b.left + cellBorder + x * (cellSize + cellBorder), b.top + cellBorder + y

* (cellSize + cellBorder), cellSize, cellSize);

}

}

}

}

}

}

package Game;

import java.awt.*;

import java.awt.event.*;

import java.awt.image.BufferedImage;

import java.io.File;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

import java.util.Scanner;

import javax.imageio.ImageIO;

import javax.swing.*;

import javax.swing.event.*;

public class MainGUI extends JFrame {

/**

* Минимальныйразмердоски

*/

private static final int MIN_BOARD_SIZE = 15;

/**

* Максимальныйразмердоски

*/

private static final int MAX_BOARD_SIZE = 50;

/**

* Размердоскипоумолчанию

*/

private static final int DEF_BOARD_SIZE = 30;

/**

* Минимальная скорость обновления симуляции в мс

*/

private static final int MIN_UPDATE_MS = 1;

/**

* Максимальная скорость обновления симуляции в мс

*/

private static final int MAX_UPDATE_MS = 100;

/**

* Скорость обновления симуляции в мс по умолчанию

*/

private static final int DEF_UPDATE_MS = 80;

/**

* Панельдлярисования

*/

private DrawingLifePanel lifePanel = null;

/**

* КнопкаЗапусксимуляции

*/

private JButton btnStart = null;

/**

* КнопкаОстановкасимуляции

*/

private JButton btnStop = null;

/**

* КнопкаЗагрузкаизфайла

*/

private JButton btnLoadFromFile = null;

/**

* КнопкаСохранениевфайл

*/

private JButton btnSaveToFile = null;

/**

* СлайдерВремяобновления

*/

private JSlider sliderUpdate = null;

/**

* СлайдерРазмерполя

*/

private JSlider sliderSize = null;

/**

* ПанельИнструменты

*/

private JToolBar toolPanel = null;

/**

* Инициализация

*/

private void Initate() {

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

setResizable(false);

lifePanel = new DrawingLifePanel();

lifePanel.initialize(DEF_BOARD_SIZE, DEF_BOARD_SIZE);

add(lifePanel);

sliderUpdate = new JSlider(MIN_UPDATE_MS, MAX_UPDATE_MS);

sliderUpdate.setValue(DEF_UPDATE_MS);

lifePanel.setUpdateDelay(sliderUpdate.getValue());

sliderSize = new JSlider(MIN_BOARD_SIZE, MAX_BOARD_SIZE);

sliderSize.setValue(DEF_BOARD_SIZE);

lifePanel.setUpdateDelay(sliderSize.getValue());

btnSaveToFile = new JButton("Сохранитьвфайл");

btnLoadFromFile = new JButton("Загрузитьизфайла");

toolPanel = new JToolBar();

toolPanel.setFloatable(false);

add(toolPanel, BorderLayout.NORTH);

toolPanel.addSeparator();

btnStart = new JButton("Запустить");

toolPanel.add(btnStart);

toolPanel.addSeparator();

btnStop = new JButton("Очиститьполе");

toolPanel.add(btnStop);

}

/**

* Добавление обработчиков событий

*/

private void AddListeners() {

sliderUpdate.addChangeListener(new ChangeListener() {

@Override public void stateChanged(ChangeEvent e) {

lifePanel.setUpdateDelay(sliderUpdate.getValue());

}

});

sliderSize.addChangeListener(new ChangeListener() {

@Override public void stateChanged(ChangeEvent e) {

lifePanel.initialize(sliderSize.getValue(), sliderSize.getValue());

lifePanel.getLifeModel().clear();

lifePanel.repaint();

}

});

btnStart.addActionListener(new ActionListener() {

@Override public void actionPerformed(ActionEvent e) {

if (lifePanel.isSimulating()) {

lifePanel.stopSimulation();

btnStart.setText("Запустить");

} else {

lifePanel.startSimulation();

btnStart.setText("Остановить");

}

}

});

btnStop.addActionListener(new ActionListener() {

@Override public void actionPerformed(ActionEvent e) {

synchronized (lifePanel.getLifeModel()) {

lifePanel.getLifeModel().clear();

lifePanel.repaint();

}

}

});

btnSaveToFile.addActionListener(new ActionListener() {

@Override public void actionPerformed(ActionEvent e) {

synchronized (lifePanel.getLifeModel()) {

try {

BufferedImage image = new BufferedImage(

lifePanel.getWidth(),

lifePanel.getHeight(),

BufferedImage.TYPE_INT_RGB

);

Graphics g = image.getGraphics();

lifePanel.paint(g);

ImageIO.write(image, "jpg", new File("LifeScreenshoot.jpg"));

FileWriter filewriter = new FileWriter(new File("LifeDB.txt"));

for (int y = 0; y < lifePanel.getLifeModel().getHeight(); y++) {

for (int x = 0; x < lifePanel.getLifeModel().getWidth(); x++) {

filewriter.write(lifePanel.getLifeModel().getCell(x, y) + " ");

}

filewriter.write("\r\n");

}

filewriter.flush();

} catch (IOException e1) {

e1.printStackTrace();

}

}

}

});

btnLoadFromFile.addActionListener(new ActionListener() {

@Override public void actionPerformed(ActionEvent e) {

synchronized (lifePanel.getLifeModel()) {

try {

byte value;

Scanner in = new Scanner(new File("LifeDB.txt"));

for (int y = 0; y < lifePanel.getLifeModel().getHeight(); y++) {

for (int x = 0; x < lifePanel.getLifeModel().getWidth(); x++) {

value = in.nextByte();

lifePanel.getLifeModel().setCell(x, y, value);

}

}

repaint();

} catch (IOException e1) {

e1.printStackTrace();

}

}

}

});

}

/**

* Конструктор

*/

public MainGUI(String title) {

super(title);

Initate();

AddListeners();

toolPanel.addSeparator();

toolPanel.add(new JLabel(" Размерполя"));

toolPanel.add(sliderSize);

toolPanel.add(new JLabel(" Скоростьигры"));

toolPanel.add(sliderUpdate);

toolPanel.addSeparator();

toolPanel.add(btnSaveToFile);

toolPanel.addSeparator();

toolPanel.add(btnLoadFromFile);

toolPanel.addSeparator();

pack();

setVisible(true);

}

/**

* Головнаяфункция

*/

public static void main(String[] args) {

try {

UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

} catch (Exception e) {}

SwingUtilities.invokeLater(new Runnable() {

public void run() {

new MainGUI("ИграЖизнь");

}

});

}

}