49182

Разработка игры «Морской бой» с ИИ

Курсовая

Информатика, кибернетика и программирование

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

Русский

2013-12-22

4.29 MB

175 чел.

Министерство образования и науки российской федерации

Государственное бюджетное образовательное учреждение высшего профессионального образования

Санкт-Петербургский национальный исследовательский университет информационных технологий, механики и оптики

ПОЯСНИТЕЛЬНАЯ ЗАПИСКА

К КУРСОВОМУ ПРОЕКТУ

по предмету «Технология разработки программных продуктов»

на тему «Разработка игры «Морской бой» с ИИ»

Программное обеспечение вычислительной техники и
автоматизированных систем (230105)

Преподаватель:

Студент гр. №

Санкт–Петербург

2013


З А Д А Н И Е

НА КУРСОВОЕ ПРОЕКТИРОВАНИЕ

Студенту:

(фамилия, имя, отчество)

Руководитель:, НИУ ИТМО, преподаватель

(фамилия, имя, отчество, место работы, должность)

1. Наименование темы: Разработка игры «Морской бой» с ИИ

2. Срок сдачи студентом законченной работы 15.06.2013

3. Техническое задание и исходные данные к работе

Техническое задание приведено в приложение 2.

4. Содержание курсовой работы (перечень подлежащих разработке вопросов)

1. Рассмотреть аналоги продукта.

2. Составить функциональные требования

3. Разработать проект разработки.

4. Разработать программный продукт.

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

5. Перечень графического материала (с указанием обязательного материала)

Диаграммы IDEF0, DFD, UML представлены в приложении 1, диаграмма Ганта представлена в пояснительной записке.

6. Исходные материалы и пособия

  1.  Базарная Е.Г. Создание Windows приложений на языке С# / Е.Г. Базарная, В.В. Изварина - СПб.: УЦВТ, 2007.
  2.  Программирование на платформе .NET Framework в Visual Studio, Web: http://msdn.microsoft.com
  3.  Visual C#, Web: http://msdn.microsoft.com
  4.  Функциональное тестирование, Web: http://www.dev-house.ru
  5.  Емельянова Н.З Основы построения автоматизированных информационных систем / Н.З.Емельянова, Т.Л.Партыка, И.И.Попов - М.: ФОРУМ: ИНФРА-М 2007.
  6.  Гагарина Л.Г. Основы технологии разработки программных продуктов / Л.Г.Гагарина, Б.Д.Виснадул, А.В. Игошин – Форум 2006.
  7.  Орлов С.А. Технологии разработки программного обеспечения / С. А. Орлов, Б. Я. Цилькер – Питер 2012.
  8.  Рудаков А.В. Технология разработки программных продуктов / А.В. Рудаков - Издательский центр "Академия" 2006.

КАЛЕНДАРНЫЙ ПЛАН

№№

п/п

Наименование этапов курсовой работы

Срок выполнения

этапов работы

Примечание

1

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

02.03.13 — 04.03.13

-

2

Определение требований

07.03.13 — 08.03.13

-

3

Проектирование

10.03.13 — 13.04.13

-

4

Разработка

20.04.13 — 10.06.13

-

5

Тестирование и Верификация

21.04.13 — 12.06.13

-

6

Документирование

02.03.13 —15.06.13

-

7

Сдача

15.06.13 — 02.07.13

-

Дата выдачи задания  

Руководитель _______________________________

   (подпись)                      

Задание принял к      

исполнению  _______________________________

   (подпись)                      



МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ

САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ

ИНФОРМАЦИОННЫХ ТЕХНОЛОГИЙ, МЕХАНИКИ И ОПТИКИ

АННОТАЦИЯ

КУРСОВОГО ПРОЕКТА

Студент

Воробьев Алексей

Факультет

СПО

Группа

333

Специальность

230105

Наименование темы

Разработка игры «Морской бой» с ИИ

Руководитель

Антонов М.Б.

КРАТКОЕ СОДЕРЖАНИЕ РАБОТЫ И ОСНОВНЫЕ ВЫВОДЫ

объем 37 стр., графический материал 13 стр., библиография 8 наименований

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

Задачи:

  1.  Анализ предметной области
  2.  Обзор аналогов продукта
  3.  Составление требований
  4.  Моделирование требований
  5.  Проектированиепрограммного продукта
  6.  Разработка программного продукта
  7.  Тестирование программного продукта
  8.  Составление документации
  9.  Исследовательская часть

Были рассмотрены различные аналоги программного продукта и их основной функционал.

  1.  Проектная часть

Проектирование производилось путём составления диаграмм UML, IDEF0, DFD, моделирующих требования к программному продукту.

  1.  Часть реализации

Программный продукт разработан с использованием языка C# ифреймворка.NETFramework 3.5.

  1.  Тестирование компонентов

Были проведены функциональное тестирование, тестирование белого ящика и альфа-тестирование

Практическая ценность работы. Рекомендации по внедрению

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

Студент

__________________

(подпись)

Руководитель

__________________

(подпись)

«___» июля 2013 г


Оглавление

ВВЕДЕНИЕ 4

1 ПОСТАНОВКА ЗАДАЧИ 8

1.1 Анализ предметной области 8

1.2 Обзор аналогов 8

1.3 Постановка задачи 10

2 ОПРЕДЕЛЕНИЕ ТРЕБОВАНИЙ 12

2.1 Моделирование требований 12

2.2 Планирование 13

2.3 Описание выполняемого технического задания 14

3 ПРОЕКТИРОВАНИЕ 16

3.1 Выбор модели системы 16

3.2 Проектирование структуры системы 16

3.2.1 Компоненты системы 16

3.2.2 Классы системы 17

3.3 Проектирование логики работы 17

3.3.1 Диаграмма деятельности 17

3.3.2 Диаграмма состояний 18

3.3.3 Диаграмма коммуникаций. 18

3.4 Проектирование интерфейса 19

4 РАЗРАБОТКА ПРОГРАММНОГО КОДА 24

5 ВЕРИФИКАЦИЯ И АТТЕСТАЦИЯ 25

5.1 Выбор методов верификации и аттестации 25

5.2 Инспектирование 25

5.3 Тестирование 27

6 ПРОГРАММНАЯ ДОКУМЕНТАЦИЯ 34

6.1 Инструкция по установке 34

6.2 Инструкция пользователя 34

ЗАКЛЮЧЕНИЕ 36

СПИСОК ИСТОЧНИКОВ ИНФОРМАЦИИ 37

Приложение 1 - Диаграммы 38

Приложение 2 - Техническое задание 51

Приложение 3 - Исходный код 56

ВВЕДЕНИЕ

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

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

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


1 ПОСТАНОВКА ЗАДАЧИ

1.1 Анализ предметной области

Игра «морской бой» представляет собой настольную игру на двух участников, которые по очереди выбирают координаты на неизвестном им поле противника. Поле представляет собой набор клеток размеров 10 на 10, на которые устанавливаются корабли. Если у соперника по этим координатам имеется корабль, то корабль или его часть «топится», а попавший получает право на ещё один ход. После уничтожения корабля клетки вокруг него отмечаются как «промахи». Цель – первым поразить все корабли соперника.

Всего кораблей в игре 10: 1 четырёхпалубный, 2 трёхпалубных, 3 двухпалубных и 4 однопалубных. Между кораблями должно быть расстояние как минимум 1 пустая клетка.

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

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

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

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

Основной целью данного программного продукта является его распространение с целью получения прибыли.

1.2 Обзораналогов

BattleshipsGeneralQuartersII.

Игра «Морской бой», выполненная не в классической форме. Всего можно расставить 5 кораблей: один на 2 клетки, два на 3 клетки, один на 4 клетки и один на 5 клеток. Корабли можно расставлять вплотную друг к другу. После каждого попадания на короткое время появляется комментарий от капитана.

Ссылка на официальную веб-страницу: http://www.battleships.f-active.com/

Battleship The Beginning.

Объёмный «Морской бой» с приятной графикой и звуковым сопровождением. Главной особенностью является наличие различных способностей, таких как подзорная труба, горящий снаряд, взрывные бочки, залповый обстрел. Также игра имеет кампанию, в ходе которой зарабатываются очки на приобретение способностей.

Ссылка на официальную веб-страницу: http://www.coolbuddy.com/games/game.asp?gid=2128

Naval Clash.

Классический «Морской бой» на ОС Android со стилистикой рисовки ручкой по бумаге. Присутствует возможность играть по Bluetooth или по сети Интернет. Довольно быстрый игровой процесс.

Ссылка на официальную веб-страницу:https://play.google.com/store/apps/details?id=northern.captain.seabattle

Морской бой, разработанный по заказу Министерства обороны РФ.

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

Ссылка на официальную веб-страницу:http://мультимедиа.минобороны.рф/multimedia/games/seabattle.htm

BattleShip Hunter.

«Морской бой» на ОС Android. Не классический стиль. Игровой процесс имеет очень простое оформление: при стрельбе по полю отмечаются либо зелёные, либо красные кружочки, в зависимости от того, было ли попадание.

Ссылка на официальную веб-страницу:http://udm4.com/Android/BattleShip_Hunter-3589302

Для сравнения аналогов были выбраны следующие параметры:

Классический стиль игры.

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

Возможность игры по сети.

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

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

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

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

Сравнение аналогов представлено в таблице 1.

Таблица 1.

Признаки сравнения

BattleshipsGeneralQuartersII

Battleship The Beginning

NavalClash

Морской бой, разработанный по заказу Министерства обороны РФ

BattleShipHunter

Классический

стиль

+

+

Дружелюбный

интерфейс

+

+

+

+/

Возможность

игрыпосети

+

Наличие

кампании

+

Звуковоесопровождение

+

+

+/–

+

Удобнаярасстановкакораблей

+

+

+

+/–

Возможностьвыборауровнясложности

+

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

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

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

Основные идеи проекта:

  1. Возможность выбора уровня сложности искусственного интеллекта.
  2. Расставить корабли на поле можно двумя способами: вручную либо автоматически.
  3. Будет вестись статистика побед и поражений с разделением на уровни сложности.Статистика будет записываться на жёстком диске, чтобы она сохранялась даже после выхода из игры.
  4. Все действия будут визуализированы: перетаскивание кораблей, наведение на клетки и надписи, результаты выстрелов.
  5. Для наглядности ИИ будет делать ходы с небольшим интервалом.
  6. Поле, по которому идёт стрельба, подсвечивается голубым цветом, а второе серым.


2 ОПРЕДЕЛЕНИЕ ТРЕБОВАНИЙ

2.1 Моделирование требований

Самая первая диаграмма IDEF0 уровня А0 отражает основную суть программного продукта – игра в морской бой. На ней в качестве исполнителей изображены игрок и процессор. Игра идёт до исчерпания количества целых кораблей у одной из команд. Диаграмма основного процесса представлена в приложении 1 на рисунке 1.

При разложении уровня А0 выделяется 3 основных процесса: выбор уровня сложности, расстановка кораблей и сам процесс игры. Все процессы последовательны и могут начаться без окончания предыдущего процесса. Развёрнутая диаграмма основного процесса представлена в приложении 1 на рисунке 2.

В связи с тем, что процесс А1 включает только 2 действия: выбор пользователем уровня сложности и записью выбора в память, он не раскладывается.

В разложении А2 (IDEF0), процессе установки корабля,на первом шаге игрок выбирает корабль, который хочет установить. Этот процесс включает в себя как выбор типа корабля, так и направление. После того, как корабль был выбран, игрок указывает место, куда он хочет его установить. Дальше программа обрабатывает корректность выбранного места, и в случае отрицательного результата происходит возврат на предыдущий процесс – выбора места установки корабля. Если проверка прошла, корабль устанавливается на поле и происходит переход на следующий процесс, в котором проверяются оставшиеся для установки корабли. Если  все корабли установлены, происходит переход к следующему процессу, иначе возврат на процесс выбора корабля. Диаграмма процесса расстановки кораблей представлена в приложении 1 на рисунке 3.

Разложение процесса игры, А3 (IDEF0), состоит из трёх циклично работающих процессов: хода игрока, хода компьютера и процесса проверки на победу и определения следующего хода, который происходит после каждого хода игрока или компьютера. Именно из этого процесса определяется победитель и происходит выход из игры. Диаграмма процесса игры представлена в приложении 1 на рисунке 4.

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

Процесс А32 – это разложение проверки на победу и определения следующего хода. Данный процесс имеет два входа в зависимости от того, кто совершал ход: игрок или ИИ. Сначала происходит проверка на попадание. Если условие не соблюдено, передаётся ход сопернику, т.е. выход из процесса с соответствующими результатами. Если попадание было, происходит проверка на уничтожение корабля. Если корабль не был уничтожен, то ход остаётся у стрелявшего и происходит выход из процесса. Если корабль уничтожен, то проверяется, остались ли ещё корабли противника в игре. Если кораблей не осталось, то это означает окончание игры. Если же корабли остались, то это действия аналогичны тому, если бы корабль не был уничтожен. Диаграмма этого процесса представлена в приложении 1 на рисунке 6.

На диаграмме Use-Case указано какие действия доступны игроку. Самое главное действие – это игра. Оно включает в себя возможность сделать выстрел. Также игрок может выбрать уровень сложности, может расставлять корабли. Кроме того игрок может посмотреть статистику и при желании сбросить её.

С диаграммой Use-Case можно ознакомиться в приложении 1 на рисунке 7.

2.2 Планирование

Планирование работы представлено в таблице 2.

Таблица 2.

ПП

Наименование

этапаработ

Срок

выполнения

Планируемаятрудоёмкость

Требуемые

ресурсы

Результат

выполнения

1

Изучениепредметнойобласти

02.03.2013- 04.03.2013

2

Задача

Определениепервичныхтребований

2

Бизнесмоделирование, изучениецелевогорынка, обзораналогов

07.03.2013 - 08.03.2013

2

Первичныетребования, задача

Целесообразностьразработкипродукта, определениеосновныхтребований

3

Концептуальноепроектирование

10.03.2013 -

14.03.2013

4

Основныетребования

Моделированиеосновныхтребований

4

Формулированиеосновныхтребований, созданиетехническогозадания

15.03.2013 - 16.03.2013

2

Основныетребования

Техническоезадание


Продолжение таблицы 2.

5

Высокоуровневоепроектированиесиспользованиемнотации UML

5.04.2013 - 13.04.2013

8

Техническоезадание

Графическоеописаниеструктурыиархитектурыпрограммногопродукта, атакжеосновныхкомпонентовиспособовихвзаимодействия

6

Разработкакода

20.04.2013 - 10.06.2013

35

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

Программныйпродукт

7

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

21.04.2013 - 12.06.2013

4

Программныйпродукт

Отлаженныйпрограммныйпродукт

8

Документирование

02.03.2013 - 30.06.2013

60

РезультатывсехработпоКП

Курсовойпроект

ДиаграммаГантапредставленанарисунке 1.

Рисунок 1.

2.3 Описание выполняемого технического задания

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

  1.  Ручная расстановка кораблей.

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

  1.  Автоматическая расстановка кораблей.

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

  1.  Стрельба по полю.

Без этого требования игра теряет смысл, оно является основным при разработке проекта. Включает выбор клетки и её обработку.

  1.  Искусственный интеллект.

Для данной разработки также является необходимым требованием. Содержит 3 различных алгоритма работы в зависимости от уровня сложности.

  1.  Выбор уровня сложности.

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


3 ПРОЕКТИРОВАНИЕ

3.1 Выбор модели системы

Модель системы данного проекта описана на диаграмме компонентов, которая представлена в приложении 1 на рисунке 9.

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

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

3.2 Проектирование структуры системы

3.2.1 Компоненты системы

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

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

Компонент обработки выстрела по клетке проверяет корректность выбранной клетки (т.е. проверка на то, не было ли по это клетке выстрела раньше, либо проверка на своё/чужое поле), а также определяет, есть ли по этой клетке попадание или нет.

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

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

3.2.2 Классы системы

Классы программного проекта изображены на диаграмме классов в приложении 1 на рисунке 10.

Основной класс – класс SeaBattle. Содержит основные функции игрового процесса и координирует работу всех функциональных классов.

Класс AI – класс искусственного интеллекта. Содержит алгоритмы работы ИИ, поля, используемые для работы этих алгоритмов, например, поля для сохранения координат первого попадания по кораблю, состояние уничтожения корабля, количество промахов для высокого уровня сложности.

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

Класс FormStatistic – окно статистики, которое содержит метод отображения результатов (show_result), метод сброса статистики и методы определения какую статистику надо выводить в зависимости от нажатой кнопки.

Классы Label (метка), Button (кнопка) и PictureBox (изображения) наследуются от базового класса для элементов управления Control, включённый в .NET Framework.

3.3 Проектирование логики работы

Логика работы программы отображена на следующих диаграммах.

3.3.1 Диаграмма деятельности

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

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

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

3.3.2 Диаграмма состояний

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

Система может находиться в шести различных состояниях.

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

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

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

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

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

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

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

3.3.3 Диаграмма коммуникаций.

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

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

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

Установка корабля взаимодействует с объектами класса Ship для обновления информации в них касательно размерности кораблей и их координат и объектом класса PictureBox, полем, для отображения корабля на поле

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

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

3.4 Проектирование интерфейса

Первый экран – меню выбора уровня сложности. Он представлен на рисунке 2. Верхняя надпись просто текст, а элементы «Лёгкий», «Нормальный» и «Сложный» - кнопки, нажатие по которым сохраняет выбранный уровень сложности и происходит переход к следующему экрану. Также тут присутствует кнопка «Статистика», которая вызывает новое окно, содержащее статистику.

Фон у главного окна: текстура воды.

Рисунок 2.

Экран расстановки кораблей представлен на рисунке 3. Слева расположено поле, на которое игрок должен расставить корабли. Сами корабли расположены справа от поля и счётчиками оставшихся кораблей. Корабль выбирается простым нажатием по нему. Под полем присутствуют две кнопки: «Сбросить» - сбрасывает все расставленные корабли, и «Случайно» - автоматически расставляет корабли. Кнопка «Статистика» присутствует на всех экранах главного окна.

Рисунок 3.

Экран игрового процесса содержит поле игрока слева и поле компьютера справа. Под каждым полем подписано чьё это поле. Оба поля постоянно подсвечены, однако цвет подсветки зависит от того, по какому полю идёт стрельба. Голубым подсвечивается поле, по которому стреляют, а серым поле, которое находится в ожидании хода.Клетки, по которым было попадания отмечены красным, а по которым промах – белым. Экран игрового процесса представлен на рисунке 4.

Рисунок 4.

Окно статистики представлено на рисунке 5. Пользователь выбирает уровень сложности, для которого он хочет посмотреть статистику. Для этого он должен нажать на одну из 3-х соответствующих кнопок. Также, нажав на кнопку «Сбросить», можно сбросить статистику. На кнопку «Закрыть» окно статистики закрывается.

Рисунок 5.


4 РАЗРАБОТКА ПРОГРАММНОГО КОДА

Для разработки программного кода был выбран язык программирования C# с использованием среды разработки VisualStudio 2010.

C# - это язык программирования, предназначенный для разработки самых разнообразных приложений, предназначенных для выполнения в среде .NET Framework. Язык C# прост, строго типизирован и объектно-ориентирован. Благодаря множеству нововведений C# обеспечивает возможность быстрой разработки приложений, но при этом сохраняет выразительность и элегантность, присущую языкам C.

Visual C# является реализацией языка C# корпорацией Майкрософт. Visual Studio поддерживает Visual C# с полнофункциональным редактором кода, компилятором, шаблонами проектов, конструкторами, мастерами кода, мощным и простым в использовании отладчиком и многими другими средствами.

Библиотека классов .NET Framework предоставляет доступ ко многим службам операционной системы и другим полезным, правильным классам, что существенно ускоряет цикл разработки.


5 ВЕРИФИКАЦИЯ И АТТЕСТАЦИЯ

5.1 Выбор методов верификации и аттестации

Функциональное тестирование рассматривает заранее указанное поведение и основывается на анализе функциональности компонента или системы в целом. В результате этого тестирования определяется, решает ли разработанное ПО задачи, ради которых оно было создано, удовлетворяет ли оно потребности заказчика/пользователя.

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

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

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

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

Для тестирование ПО были выбраны следующие методы: функциональное тестирование, тестирование белого ящика, ручное тестирование и альфа-тестирование.

5.2 Инспектирование

Выделение требований из ТЗ

  1.  Пользовать должен иметь возможность начать игру.
  2.  Пользовать должен иметь возможность выбрать сложность ИИ.
  3.  Пользователь должен иметь возможность расставить корабли вручную.
  4.  Пользователь должен иметь возможность выбрать автоматическую расстановку кораблей.
  5.  После ручной расстановки кораблей должна производиться проверка на правильность расстановки.
  6.  ИИ должен быть 3-х уровней: легкий, средний, сложный.
  7.  После хода должна производиться проверка на попадание.
  8.  Игра должна прекращаться после уничтожения всех кораблей.
  9.  Пользователь не должен видеть на поле противника его корабли.

Оценка качества выполнения требованийпредставлена в таблице 3.

Таблица 3.

Требование

Оценка

Комментарий

Пользовать должен иметь возможность начать игру

5

Отображено на всех диаграммах

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

5

Отображено на всех диаграммах

Пользователь должен иметь возможность расставить корабли вручную

5

Отображено на всех диаграммах

Пользователь должен иметь возможность выбрать автоматическую расстановку кораблей

5

Очень подробно рассмотрена в StateMachineDiagram

После ручной расстановки кораблей должна производиться проверка на правильность расстановки

4

Присутствует на Activity Diagram

ИИ должен быть 3-х уровней: легкий, средний, сложный

5

Отображено на всех диаграммах

После хода должна производиться проверка на попадание

5

Отображено на всех диаграммах

Игра должна прекращаться после уничтожения всех кораблей

5

Отображено на всех диаграммах

Пользователь не должен видеть на поле противника его корабли

5

Не указано явно, но подразумевается

Оценка требований ТЗ по правильности формулировок представлена в таблице 4.

Таблица 4.

Тип требования

Оценка

Комментарии

Описание классов пользователей

5

Указан один класс пользователя

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

5

Дано полное описание функций, их реализация и условия проверки

Описание входных и выходных данных

5

Входные и выходные данные подробно описаны для каждой функции

Продолжение таблицы 4.

Требования к защите информации

5

Скрытие кораблей противника

Требования к аппаратно-программному комплексу

4

Указаны требования к программному комплексу

Комплексная оценка

Сделаны подробные диаграммы, содержащие все поставленные требования; требования ТЗ сформулированы грамотно и лаконично. Склоняюсь к комплексной оценке – 10 баллов.

5.3 Тестирование

Функциональное тестирование.

Проверка меню выбора уровня сложности. При наведении на кнопки меню, они выделяются, а при нажатии происходит переход на следующий экран. Скриншот приведён на рисунке6.

Рисунок 6.

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

Рисунок 7.

При нажатии на кнопку «Случайно» корабли расставляются корректно, а при нажатии на кнопку «Сброс» поле очищается. Результат авто расстановки можно увидеть на рисунке 8, а очистки на рисунке 9.

Рисунок 8.

Рисунок 9.

Игровой процесс. При наведении на клетку она выделяется. При нажатии на неё поле обновляется, отображая, было ли попадание. Если был промах, то ход передаётся противнику. При этом соответственно меняется подсветка поля. При уничтожении корабля клетки вокруг него отмечаются как промах. Искусственный интеллект действует согласно выбранному уровню сложности.Игровой процесс приведён на рисунке 10.

Рисунок 10.

По окончанию игры выводится соответствующее сообщение и происходит запись в статистику. Результат при победе отображён на рисунке 11.

Рисунок 11.

Окно статистики приведено на рисунке 12. При нажатии на кнопки выбора уровня сложности данные выводятся правильно. После нажатия на кнопку сброс статистика сбрасывается (рисунок 13).

Рисунок 12.

Рисунок 13.

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

При проведении тестирования по методу «белого ящика» были проверены все функции и все возможные ветки программного кода. Ошибок обнаружено не было.

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

6 ПРОГРАММНАЯ ДОКУМЕНТАЦИЯ

6.1 Инструкция по установке

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

Для работы приложения должна быть установлена программная платформа .NET Framework версии 3.5 и выше. Скачать её можно бесплатнос официального сайта Microsoft.

Минимальные требования:

Операционная система WindowsXPи выше, разрядностью 32 или 64 бита.

Процессор с частотой 400 МГц.

ОЗУ 96 МБ.

Место на жёстком диске: 300 МБ для 32-х разрядной системы и 620 МБ для 64-х разрядной.

6.2 Инструкция пользователя

Для запуска нужно запустить файл SeaBattle.exe.

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

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

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

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


ЗАКЛЮЧЕНИЕ

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

  1.  различные уровни сложности игры;
  2.  автоматическая расстановка кораблей;
  3.  искусственный интеллект;
  4.  визуализация интерфейса;
  5.  статистика.

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

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

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

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

СПИСОК ИСТОЧНИКОВ ИНФОРМАЦИИ

  1.  Базарная Е.Г. Создание Windows приложений на языке С# / Е.Г. Базарная, В.В. Изварина - СПб.: УЦВТ, 2007.
  2.  Программирование на платформе .NET Framework в Visual Studio, Web: http://msdn.microsoft.com
  3.  Visual C#, Web: http://msdn.microsoft.com
  4.  Функциональное тестирование, Web: http://www.dev-house.ru
  5.  Емельянова Н.З Основы построения автоматизированных информационных систем / Н.З.Емельянова, Т.Л.Партыка, И.И.Попов - М.: ФОРУМ: ИНФРА-М 2007.
  6.  Гагарина Л.Г. Основы технологии разработки программных продуктов / Л.Г.Гагарина, Б.Д.Виснадул, А.В. Игошин –Форум 2006.
  7.  Орлов С.А. Технологии разработки программного обеспечения / С. А. Орлов, Б. Я. Цилькер – Питер 2012.
  8.  Рудаков А.В. Технология разработки программных продуктов / А.В. Рудаков - Издательский центр "Академия" 2006.


Приложение 1 - Диаграммы

Рисунок 1 - Диаграмма основного процесса

Рисунок 2 - Развёрнутая диаграмма основного процесса

Рисунок 3 - Развёрнутая диаграмма процесса расстановки кораблей

Рисунок 4 - Диаграмма процесса игры

 

Рисунок 5 -Диаграмма хода игрока

Рисунок 6 -Диаграмма проверки на победу и следующего хода

Рисунок 7. Диаграмма Use-Case

Рисунок 8. Component Diagram

 

Рисунок 9. Class Diagram



Рисунок 10. Activity Diagram

Рисунок 11. State Machine Diagram

 

Рисунок 12. Communication Diagram


Рисунок 13. Sequence Diagram

Приложение 2 - Техническое задание

1 Назначение разработки

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

2 Цель и задачи

Цель: разработать программный продукт, реализующий игру «Морской бой».

Задачи:

  1.  Реализовать оформление приложения, расположить элементы управления.
  2.  Разработать функцию генерации поля.
  3.  Разработать функции навигации и стрельбы по полю.
  4.  Разработать алгоритмы искусственного интеллекта.
  5.  Реализовать работу со статистикой.

3 Требования к разработке

3.1 Описание классов пользователей

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

3.2 Требования к функциональным характеристикам

Список функций:

Функция 1.

Имя: Начало игры.

Описание: Начать игру необходимо для того, чтобы играть в «Морской бой».

Реализация: Нажать кнопку «Новая игра».

Проверка: Произошёл переход в следующее меню.

Функция 2.

Имя: Уровень сложности.

Описание: Необходимо выбрать уровень сложности ИИ и подтвердить выбор. Дальше произойдёт переход в следующее меню.

Реализация: Выбрать соответствующее значение из вариантов.

Проверка: Слежение за поведением ИИ.

Функция 3.

Имя: Расстановка кораблей вручную.

Описание: Перед началом игры необходимо расставить корабли.

Реализация: Выбирается корабль и размещается в свободное место с учётом ограничений расстановки кораблей. После размещения происходит проверка на корректность выбора места расстановки (расстояние между кораблями не может быть меньше 1 клетки, корабль должен полностью находиться в пределах поля). Таким образом генерируется поле. Это поле хранится в виде массива. Когда все корабли будут размещены, станет активна кнопка начала игры.

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

Функция 4.

Имя: Автоматическая расстановка кораблей.

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

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

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

Функция 5.

Имя: Выстрел.

Описание: Необходимо после каждого хода проверять было ли попадание.

Реализация: Поля организовываются следующим образом: двумерный массив со значениями 0 (пустая клетка), 1 (находится корабль), 2 (промах) и 3 (было попадание). После каждого выстрела происходит проверка на попадание (в указанной клетке стоит значение “1”). Если это так, то значение меняется на “3” и даётся ещё один ход стрелявшему. Если попадания не было (выстрел по клетке “0”), передать ход противнику и изменить значение на “2”. Если по выбранной клетке уже был выстрел (значения “2” или “3”), необходимо соответственно предупредить об этом. После каждого выстрела массив обновляется и обновляется визуальное поле.

Проверка: Все выстрелы отмечаются корректно.

Функция 6.

Имя: Искусственный интеллект.

Описание: Реализация искусственного интеллекта с учётом уровня сложности.

Реализация: При вызове этой функции передаётся массив с полем игрока. При обработке значение “1” определяется наравне с “0”, кроме сложного уровня сложности при определённых условиях.

В зависимости от уровня сложности определяется поведение ИИ.

Лёгкий уровень: ИИ стреляет абсолютно случайно после каждого хода.

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

Сложный уровень: ИИ делает случайные выстрелы, но на третьем обязательно попадает. После этого со 100% вероятностью добивает корабль. Дальше опять не более двух промахов и так далее.

Проверка: ИИ должен себя вести себя корректно.

Функция 7.

Имя: Конец игры.

Описание: Окончание игры после уничтожения всех кораблей.

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

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

3.3 Описание входных и выходных данных

Описание входных и выходных данных представлено в таблице 1.

Таблица 1.

Функция

Входные параметры

Выходные параметры

Начало игры

Вывод следующего меню

Уровень сложности

Значение уровня сложности

Вывод следующего меню

Расстановка кораблей вручную

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

Сгенерированное поле (массив)

Автоматическая расстановка кораблей

Сгенерированное поле (массив)

Продолжение таблицы 1.

Выстрел

Поле, позиция на поле

Поле

Искусственный интеллект

Поле

Поле

Конец игры

Оставшиеся корабли, уничтоженные корабли

Кораблей не осталось: победа

Иначе: false

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

Требования к надёжности не предъявляются.

3.5 Эргономические и техникоэстетические требования

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

3.6 Требования к защите информации

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

3.7 Другие требования к разработке

Другие требования к разработке не определены.

3.8 Требования к аппаратно-программному комплексу

Требования к аппаратному обеспечению:

  1.  Оперативная память: от 256МБ.
  2.  Процессор: 1 ГГц и выше.
  3.  Места на жёстком диске: 300 МБ для 32-х разрядной системы и 620 МБ для 64-х разрядной.

Требования к программному обеспечению:

  1.  Операционная система WindowsXP/Vista/7/8.
  2.  Программная платформа .NET Framework версии 3.5 и выше.

3.9 Требования к технологиям разработки

Программныйкомплекс: MicrosoftVisualStudio 2010 (C#).

3.10 Требования к составу технических средств при эксплуатации

Не определены.


Приложение3 - Исходный код

Файл Form1.cs

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

using WMPLib;

using System.Diagnostics;

using System.IO;

namespace SeaBattle

{

   public partial class SeaBattle : Form

   {

       public SeaBattle()

       {

           InitializeComponent();

       }

       WMPLib.WindowsMediaPlayer audio = new WMPLib.WindowsMediaPlayer();

       int[,] field_player = new int[11, 11];

       int[,] field_enemy = new int[11, 11];

       int ship_count_p = 0;

       int ship_count_e = 0;

       Ship[] ships = new Ship[10];

       Ship[] ships_e = new Ship[10];

       AI ArtInt = new AI();

       int dir = 1;

int cur_stat = 0; //размер выбранного корабля

PictureBox[,] pictureBox = new PictureBox[11, 11];

       int count4 = 1;

       int count3 = 2;

       int count2 = 3;

       int count1 = 4;

       int difficult; //1 - easy, 2 - normal, 3 - hard

       FormStatistic FrmStat = new FormStatistic(); //Формаправил

       public void Wait(int value)

       {

           Stopwatch sw = new Stopwatch();

           sw.Start();

           while (sw.ElapsedMilliseconds < value)

               Application.DoEvents();

       } //функцияожидания

       public int[] get_coord(PictureBox pic)

       {

           int n_1, n_2;

           int[] ret = new int[2];

           string dot_name = pic.Name.Remove(0, 4); //обрезкавименичасти p_x_

           if (dot_name.Length == 3) //еслидлина = 3

if (dot_name[1] == '0') //определение клетки (первый номер 10)

{

                   n_1 = Convert.ToInt32(dot_name.Remove(2, 1));

                   n_2 = Convert.ToInt32(dot_name.Remove(0, 2));

}

               else //определение клетки (второй номер 10)

{

                   n_1 = Convert.ToInt32(dot_name.Remove(1, 2));

                   n_2 = Convert.ToInt32(dot_name.Remove(0, 1));

}

           else if (dot_name.Length == 2) //определение клетки (две цифры)

{

               n_1 = Convert.ToInt32(dot_name.Remove(1, 1));

               n_2 = Convert.ToInt32(dot_name.Remove(0, 1));

}

           else //определение клетки (10 10)

           {

               n_1 = 10;

               n_2 = 10;

}

           ret[0] = n_1;

           ret[1] = n_2;

           return ret;

} //функция определения координат клетки по PictureBox

public void draw_field(string side)

       {

           int i, j;

           int[,] field = new int[11, 11];

           if (side == "p_a_")

               field = field_player;

           else if (side == "p_b_")

               field = field_enemy;

           for (i = 1; i < 11; i++)

               for (j = 1; j < 11; j++)

                   switch (field[i, j])

                   {

                       case 0: (Controls[side + i + j] as PictureBox).Image = Properties.Resources.dot2; break;

                       case 1:

                           {

                               if (side == "p_b_")

                                   (Controls[side + i + j] as PictureBox).Image = Properties.Resources.dot2;

                               else

                                   (Controls[side + i + j] as PictureBox).Image = Properties.Resources.dot_ship_set;

                               break;

                           }

                       case 2: (Controls[side + i + j] as PictureBox).Image = Properties.Resources.dot_miss; break;

                       case 3: (Controls[side + i + j] as PictureBox).Image = Properties.Resources.hit; break;

                       case 4: (Controls[side + i + j] as PictureBox).Image = Properties.Resources.dot_ship_destroyed; break;

                       case 5: (Controls[side + i + j] as PictureBox).Image = Properties.Resources.dot_ship_contur; break;

                       case 6: (Controls[side + i + j] as PictureBox).Image = Properties.Resources.dot2; break;

                       case 7:

                       case 8:

                       case 9: (Controls[side + i + j] as PictureBox).Image = Properties.Resources.dot_ship_set_err; break;

                   }

       } //перерисовкаполя

       public int ai_hit(int n1, int n2, Ship shp)

       {

           PictureBox pic = Controls["p_a_" + n1 + n2] as PictureBox;

           for (int i = 0; i < shp.get_n(); i++)

           {

               if (pic.Name == "p_a_" + shp.sq[i].x.ToString() + shp.sq[i].y.ToString())

               {

                   shp.sq[i].stat = 0;

                   field_player[shp.sq[i].x, shp.sq[i].y] = 3;

                   pic.Tag = "3";

                   field_player = shp.ship_check(field_player);

                   return 1;

               }

           }

           return 0;

       } //обработкапопаданияИИ

       public void turn()

{

int i;

           int[] crd = new int[1]; //массив, содержащий 2 координаты выбранной ИИ клетки

glow_enemy.Image = Properties.Resources.glow_gray;

           glow_player.Image = Properties.Resources.glow_blue;

           ArtInt.set_turn(true);

           while (ArtInt.get_turn()) //покаходитИИ

{

               switch (difficult) //получение координат выбранной ИИ клетки

{

                   case 1: crd = ArtInt.select_dot_1(field_player); //лёгкийуровень

                       break;

                   case 2: crd = ArtInt.select_dot_2_3(field_player,2); //среднийуровень

                       break;

                   case 3: crd = ArtInt.select_dot_2_3(field_player, 3); //среднийуровень

                       break;

               }

               if (field_player[crd[0], crd[1]] == 1) //еслиИИпопал

{

                   for (i = 0; ai_hit(crd[0], crd[1], ships[i]) == 0; i++) ; //цикл по всем кораблям, пока не будет найден тот, в который было попадание

if (ships[i].destr == 1) //еслиИИуничтожилкорабль

                   {

                       ArtInt.set_turn(true);

                       ArtInt.hit = false;

                       ArtInt.destr_in_proc = 0;

                       ArtInt.dir = 0;

                   }

                   else if (ships[i].destr == 0) //еслиИИнеуничтожилкорабль

                   {

                       ArtInt.set_turn(true);

                       ArtInt.hit=true;

                       if (ArtInt.destr_in_proc == 0)

                       {

                           ArtInt.destr_in_proc = 1;

                           ArtInt.set_last(crd[0], crd[1]);

                       }

                   }

               }

               else //еслиИИпромахнулся

               {

                   field_player[crd[0], crd[1]] = 2; //отметкаклеткикакпромах

ArtInt.set_turn(false); //передачаходаигроку

               }

draw_field("p_a_"); //перерисовка поля игрока

               Wait(500); //приостановка

               check_win(); //проверка на победу

glow_enemy.Image = Properties.Resources.glow_blue;

               glow_player.Image = Properties.Resources.glow_gray;

           }

       }

       public void auto_set(string side)

       {

           int i, count_4_e = 1, count_3_e = 2, count_2_e = 3, count_1_e = 4, number1, number2, num_dir;

           int[,] field = new int[11, 11];

           if (side == "p_a_")

               field = field_player;

           else if (side == "p_b_")

               field = field_enemy;

           Random rnd = new Random();

           number1 = rnd.Next(1, 11); //x

           number2 = rnd.Next(1, 11); //y

           num_dir = rnd.Next(1, 3); //ось

           dir = num_dir;

cur_stat = 4;

           for (i = 1; i < 11; i++) //установка кораблей противника

{

               while (ship_set_check(field, number1, number2, side) != 1) //пока выбранное место для установки корабля некорректно

{

                   number1 = rnd.Next(1, 11);

                   number2 = rnd.Next(1, 11);

                   num_dir = rnd.Next(1, 3);

                   dir = num_dir;

               }

               move_ship(field, Controls[side + number1 + number2] as PictureBox, 3, side);

               switch (cur_stat)

               {

                   case 4: { count_4_e--; cur_stat = 3; break; }

                   case 3:

                       {

                           count_3_e--;

                           if (count_3_e == 0)

                               cur_stat = 2;

                           break;

                       }

                   case 2:

                       {

                           count_2_e--;

                           if (count_2_e == 0)

                               cur_stat = 1;

                           break;

                       }

                   case 1:

                       {

                           count_1_e--;

                           if (count_1_e == 0)

                               cur_stat = 0;

                           break;

                       }

               }

           }

       }

       public int ship_set_check(int[,] field, int n_1, int n_2, string side)   //функцияпроверкикорректностирасстановкикорабля

       {                                                                        //dir: 1 - horiz, 2 - vert

           int vert = 0, horiz = 0;

           for (int i = 0; i < cur_stat; i++)

{ //цикл по размеру корабля

               if (dir == 1) horiz = i; //сдвиг по горизонтали

else if (dir == 2) vert = i; //сдвигповертикали

if ((n_2 + horiz) < 11 && (n_1 + vert) < 11) //если клетка не выходит за пределы поля

               {

                   if (field[n_1 + vert, n_2 + horiz] == 1 || field[n_1 + vert, n_2 + horiz] == 6 || field[n_1 + vert, n_2 + horiz] == 9) //в выбранной клетке стоит корабль (1) или рядом с ним (6)

                       return 0; //проверка не прошла (корабль)

               }

               else return 2; //проверка не прошла (границы)

           }

           return 1; //возврат результата проверки

       }

       public void move_ship(int[,] field, PictureBox pic, int act, string side) //визуальное перемещение корабля

       {

           //act 1 - отображение наведения 2 - снять наведение 3 - клик

string dot_name = pic.Name.Remove(0, 4); //обрезкавименичасти p_x_

           int i, n_1, n_2, vert = 0, horiz = 0;

           n_1 = get_coord(pic)[0];

           n_2 = get_coord(pic)[1];

           int shp_all = ship_set_check(field, n_1, n_2, side);

           //         if (act == 3 && shp_all == 1) ships[ship_count] = new Ship(4,10);

for (i = 0; i < cur_stat; i++) //визуальное отображение корабля вместо курсора

{

               if (dir == 1) horiz = i;

               else if (dir == 2) vert = i;

               if (n_1 + vert < 11 && n_2 + horiz < 11) if (field[n_1 + vert, n_2 + horiz] != 1)

                       if (act == 1)

                       {

                           if (shp_all == 1 && field[n_1 + vert, n_2 + horiz] != 1 && field[n_1 + vert, n_2 + horiz] != 6) //если проверка на корректность установки прошла

field[n_1 + vert, n_2 + horiz] = 5;

else if (shp_all == 0) //если не прошла (корабль)

if (field[n_1 + vert, n_2 + horiz] == 6) //клеткаоколокорабля

                                   field[n_1 + vert, n_2 + horiz] = 9;

                               else field[n_1 + vert, n_2 + horiz] = 7;

else //если не прошла (границы)

field[n_1 + vert, n_2 + horiz] = 8;

                           //                     (Controls[side + (n_1 + vert) + (n_2 + horiz)] as PictureBox).Tag = "5"; хззачемэтотутбыло

                       }

                       else if (act == 2)

                       {

                           switch (field[n_1 + vert, n_2 + horiz])

                           {

                               case 5:

                               case 8: field[n_1 + vert, n_2 + horiz] = 0; break;

                               case 7: field[n_1 + vert, n_2 + horiz] = 0; break;

                               case 9: field[n_1 + vert, n_2 + horiz] = 6; break;

                           }

                       }

                       else if (act == 3)

                       {

                           switch (field[n_1 + vert, n_2 + horiz])

                           {

                               case 5:

                               case 8: field[n_1 + vert, n_2 + horiz] = 0; break;

                               case 7: field[n_1 + vert, n_2 + horiz] = 0; break;

                               case 9: field[n_1 + vert, n_2 + horiz] = 6; break;

}

                           if (shp_all == 1) //если проверка на корректность установки прошла

{

                               if (i == 0)

                               {

                                   switch (cur_stat)

                                   {

                                       case 4: { count4--; lbl1.Text = "x" + count4.ToString(); break; }

                                       case 3: { count3--; lbl2.Text = "x" + count3.ToString(); break; }

                                       case 2: { count2--; lbl3.Text = "x" + count2.ToString(); break; }

                                       case 1: { count1--; lbl4.Text = "x" + count1.ToString(); break; }

                                   }

                                   if (count1 == 0 && count2 == 0 && count3 == 0 && count4 == 0)

                                       btn_Battle.Visible = true;

                                   if (side == "p_a_")

                                   {

                                       ships[ship_count_p] = new Ship(cur_stat);

                                       ship_count_p++;

                                   }

                                   else if (side == "p_b_")

                                   {

                                       ships_e[ship_count_e] = new Ship(cur_stat);

                                       ship_count_e++;

                                   }

                               }

                               field[n_1 + vert, n_2 + horiz] = 1;

                               if (side == "p_a_")

                               {

                                   ships[ship_count_p - 1].sq[i].x = n_1 + vert;

                                   ships[ship_count_p - 1].sq[i].y = n_2 + horiz;

                               }

                               if (side == "p_b_")

                               {

                                   ships_e[ship_count_e - 1].sq[i].x = n_1 + vert;

                                   ships_e[ship_count_e - 1].sq[i].y = n_2 + horiz;

                               }

                               (Controls[side + (n_1 + vert) + (n_2 + horiz)] as PictureBox).Tag = "1";

                               if ((n_1 + 1 + vert) < 11)

                                   if (field[n_1 + 1 + vert, n_2 + horiz] == 0)

                                       field[n_1 + 1 + vert, n_2 + horiz] = 6; //низ

                               if ((n_2 + 1 + horiz) < 11)

                                   if (field[n_1 + vert, n_2 + 1 + horiz] == 0)

                                       field[n_1 + vert, n_2 + 1 + horiz] = 6; //право

                               if ((n_1 - 1 + vert) > 0)

                                   if (field[n_1 - 1 + vert, n_2 + horiz] == 0)

                                       field[n_1 - 1 + vert, n_2 + horiz] = 6; //верх

                               if ((n_2 - 1 + horiz) > 0)

                                   if (field[n_1 + vert, n_2 - 1 + horiz] == 0)

                                       field[n_1 + vert, n_2 - 1 + horiz] = 6; //лево

                               if ((n_2 - 1 + horiz) > 0 && (n_1 - 1 + vert) > 0)

                                   if (field[n_1 - 1 + vert, n_2 - 1 + horiz] == 0)

                                       field[n_1 - 1 + vert, n_2 - 1 + horiz] = 6; //лево-верх

                               if ((n_2 - 1 + horiz) > 0 && (n_1 + 1 + vert) < 11)

                                   if (field[n_1 + 1 + vert, n_2 - 1 + horiz] == 0)

                                       field[n_1 + 1 + vert, n_2 - 1 + horiz] = 6; //лево-низ

                               if ((n_2 + 1 + horiz) < 11 && (n_1 - 1 + vert) > 0)

                                   if (field[n_1 - 1 + vert, n_2 + 1 + horiz] == 0)

                                       field[n_1 - 1 + vert, n_2 + 1 + horiz] = 6; //право-верх

                               if ((n_2 + 1 + horiz) < 11 && (n_1 + 1 + vert) < 11)

                                   if (field[n_1 + 1 + vert, n_2 + 1 + horiz] == 0)

                                       field[n_1 + 1 + vert, n_2 + 1 + horiz] = 6; //право-низ

                           }

                       }

           }

           //  if (act == 3 && shp_all == 1) { cur_stat = 0; ship_count++; };

       }

       public void generate_field(int x, int y, string side)

       {

           int i, j, min_dist = 19;

           for (i = 1; i < 11; i++)

           {

               for (j = 1; j < 11; j++)

               {

                   pictureBox[i, j] = new PictureBox();

                   pictureBox[i, j].Name = side + j + i;

                   pictureBox[i, j].Image = Properties.Resources.dot2;

                   pictureBox[i, j].Location = new Point(min_dist * (i - 1) + x, min_dist * (j - 1) + y);

                   pictureBox[i, j].Size = new Size(20, 20);

                   //pictureBox[i, j].Tag = String.Format("{0} {1}", j, i);

                   pictureBox[i, j].Tag = "0";

                   pictureBox[i, j].BringToFront();

                   pictureBox[i, j].Click += new EventHandler(click);

                   pictureBox[i, j].MouseEnter += new EventHandler(mas_MouseMove);

                   pictureBox[i, j].MouseLeave += new EventHandler(mas_MouseLeave);

                   this.Controls.Add(pictureBox[i, j]);

                   glow_player.SendToBack();

                   glow_enemy.SendToBack();

               }

           }

       } //генерацияполя

       public void check_dot(PictureBox pic, Ship shp) //проверкаклетки

       {

           string dot_name = pic.Name.Remove(0, 4); //обрезкавименичасти p_x_

           string side = pic.Name.Remove(4, pic.Name.Length - 4);

           int[,] field = new int[11, 11];

           int n_1, n_2;

           if (side == "p_a_")

               field = field_player;

           else if (side == "p_b_")

               field = field_enemy;

           n_1 = get_coord(pic)[0];

           n_2 = get_coord(pic)[1];

           for (int i = 0; i < shp.get_n(); i++)

           {

               if (pic.Name == side + shp.sq[i].x.ToString() + shp.sq[i].y.ToString())

               {

                   shp.sq[i].stat = 0;

                   field[shp.sq[i].x, shp.sq[i].y] = 3;

                   pic.Tag = "3";

                   field_enemy = shp.ship_check(field_enemy);

                   draw_field("p_b_");

                   check_win();

                   break;

               }

               else

                   if (pic.Tag.ToString() == "0")

                   {

                       pic.Tag = 2;

                       field[n_1, n_2] = 2;

                       draw_field("p_b_");

                       turn();

                   }

           }

       }

       public void statistic_edit(int side, int diff) //side 1 - игрок, 2 - ИИ

       {

           int[] stat = new int[6];

           StreamReader sr = new StreamReader("stat");

           for (int i = 0; i < 6; i++)

               stat[i] = Convert.ToInt32(sr.ReadLine());

           sr.Close();

           switch (diff)

           {

               case 1:

                   if (side == 1)

                       stat[0]++;

                   else

                       stat[1]++;

                   break;

               case 2:

                   if (side == 1)

                       stat[2]++;

                   else

                       stat[3]++;

                   break;

               case 3:

                   if (side == 1)

                       stat[4]++;

                   else

                       stat[5]++;

                   break;

           }

           StreamWriter sw = new StreamWriter("stat");

           for (int i = 0; i < 6; i++)

               sw.WriteLine(stat[i]);

           sw.Close();

       }

       publicvoidcheck_win() //проверканапобеду

{

           int victory=1;

           for (int i = 0; i < ship_count_e; i++)

               if (ships_e[i].destr == 0)

                   victory = 0;

           if (victory == 1)

           {

               statistic_edit(1, difficult);

               DialogResult result = MessageBox.Show("Вывыиграли! Хотитесыгратьещёраз?", "Победа!", MessageBoxButtons.YesNo);

               if (result == System.Windows.Forms.DialogResult.Yes)

               {

                   Application.Restart();

                   Environment.Exit(0);

               }

               else

                   Environment.Exit(0);

           }

           victory = 1;

           for (int i = 0; i < ship_count_p; i++)

               if (ships[i].destr == 0)

                   victory = 0;

           if (victory == 1)

           {

               statistic_edit(0, difficult);

               DialogResult result = MessageBox.Show("Выпроиграли. Хотитесыгратьещёраз?", "Поражение", MessageBoxButtons.YesNo);

               if (result == System.Windows.Forms.DialogResult.Yes)

               {

                   Application.Restart();

                   Environment.Exit(0);

               }

               else

                   Environment.Exit(0);

           }

       }

       private void btn_Battle_Click(object sender, EventArgs e)

       {

           int i;

           btn_Battle.Visible = false;

           pic_reset.Visible = false;

           pic_auto.Visible = false;

//           pic_x.Visible = true;

//           pic_dualshock.Visible = true;

           for (i = 1; i <= 7; i++)

               Controls["pic_ship" + i].Visible = false;

           for (i = 1; i <= 4; i++)

               Controls["lbl" + i].Visible = false;

           generate_field(400, 115, "p_b_");

           auto_set("p_b_");

           draw_field("p_b_");

           glow_enemy.Visible = true;

           glow_player.Visible = true;

           your_field.Visible = true;

           en_field.Visible = true;

       }

       void click(object sender, EventArgs e) //кликпополю

       {

           if (sender is PictureBox)

           {

               if (cur_stat != 0) //есливыбранкорабль

                   move_ship(field_player, sender as PictureBox, 3, "p_a_");

               else

               {

                   int n_1, n_2;

                   n_1 = get_coord(sender as PictureBox)[0];

                   n_2 = get_coord(sender as PictureBox)[1];

                   if (!ArtInt.get_turn())

                       if ((sender as PictureBox).Name.Remove(4, (sender as PictureBox).Name.Length - 4) == "p_b_" && field_enemy[n_1,n_2]!=2)

                       {

                           for (int i = 0; i < ship_count_e; i++)

                               check_dot(sender as PictureBox, ships_e[i]);

                           draw_field("p_b_");

                       }

               }

           }

           cur_stat = 0;

           draw_field("p_a_");

       }

       private void SeaBattle_Load(object sender, EventArgs e)

       {

           btn_Battle.MouseEnter += (a_sender, a_args) =>

           {

               PictureBox pic = a_sender as PictureBox;

               pic.Image = Properties.Resources.btn_Battle_1;

           };

           btn_Battle.MouseLeave += (a_sender, a_args) =>

           {

               PictureBox pic = a_sender as PictureBox;

               pic.Image = Properties.Resources.btn_Battle_pressed;

           };

           if (!System.IO.File.Exists("stat"))

           {

               StreamWriter sw = File.CreateText("stat");

               for (int i = 0; i < 6; i++)

                   sw.WriteLine("0");

               sw.Close();

           }

           pic_ship7.MouseDown += new MouseEventHandler(MouseDown_ship);

           pic_ship6.MouseDown += new MouseEventHandler(MouseDown_ship);

           pic_ship5.MouseDown += new MouseEventHandler(MouseDown_ship);

           pic_ship4.MouseDown += new MouseEventHandler(MouseDown_ship);

           pic_ship3.MouseDown += new MouseEventHandler(MouseDown_ship);

           pic_ship2.MouseDown += new MouseEventHandler(MouseDown_ship);

           pic_ship1.MouseDown += new MouseEventHandler(MouseDown_ship);

           pic_reset.MouseEnter += new EventHandler(mouse_e);

           pic_reset.MouseLeave += new EventHandler(mouse_l);

           pic_auto.MouseEnter += new EventHandler(mouse_e);

           pic_auto.MouseLeave += new EventHandler(mouse_l);

           pic_easy.MouseEnter += new EventHandler(mouse_enter_diff);

           pic_easy.MouseLeave += new EventHandler(mouse_leave_diff);

           pic_easy.Click += new EventHandler(mouse_click_diff);

           pic_normal.MouseEnter += new EventHandler(mouse_enter_diff);

           pic_normal.MouseLeave += new EventHandler(mouse_leave_diff);

           pic_normal.Click += new EventHandler(mouse_click_diff);

           pic_hard.MouseEnter += new EventHandler(mouse_enter_diff);

           pic_hard.MouseLeave += new EventHandler(mouse_leave_diff);

           pic_hard.Click += new EventHandler(mouse_click_diff);

           pic_statistic.MouseEnter += new EventHandler(mouse_enter_stat);

           pic_statistic.MouseLeave += new EventHandler(mouse_leave_stat);

           pic_statistic.Click += new EventHandler(mouse_click_stat);

       }

       private void mas_MouseMove(object sender, EventArgs e) //наведениенаклетку

       {

           int n_1, n_2;

           string name = (sender as PictureBox).Name.Remove(4, (sender as PictureBox).Name.Length - 4);

           n_1 = get_coord(sender as PictureBox)[0];

           n_2 = get_coord(sender as PictureBox)[1];

           if ((sender as PictureBox).Tag.ToString() == "0" || (name == "p_b_") && (sender as PictureBox).Tag.ToString() == "1")

{

               if (cur_stat != 0)

{

                   move_ship(field_player, sender as PictureBox, 1, "p_a_");

                   draw_field("p_a_");

               }

               else try

                   {

                       if ((name == "p_a_" && field_player[n_1, n_2] != 2) || (name == "p_b_" && field_enemy[n_1, n_2] != 2))

                           (sender as PictureBox).Image = Properties.Resources.dot_target;

                   }

                   catch { };

           }

       }

       private void mas_MouseLeave(object sender, EventArgs e)

       {

           int n_1, n_2;

           string name = (sender as PictureBox).Name.Remove(4, (sender as PictureBox).Name.Length - 4);

           n_1 = get_coord(sender as PictureBox)[0];

           n_2 = get_coord(sender as PictureBox)[1];

           move_ship(field_player, sender as PictureBox, 2, "p_a_");

           if ((sender as PictureBox).Tag.ToString() == "0" || (name == "p_b_") && (sender as PictureBox).Tag.ToString() == "1")

               if ((name == "p_a_" && field_player[n_1, n_2] != 2) || (name == "p_b_" && field_enemy[n_1, n_2] != 2))

                   (sender as PictureBox).Image = Properties.Resources.dot2;

       } //выходизклетки

       private void MouseDown_ship(object sender, EventArgs e) //кликпоиконкамкораблей

       {

           switch ((sender as PictureBox).Name.ToString())

           {

               case "pic_ship1": if (count1 > 0) { cur_stat = 1; dir = 1; } break;

               case "pic_ship2": if (count2 > 0) { cur_stat = 2; dir = 1; } break;

               case "pic_ship3": if (count3 > 0) { cur_stat = 3; dir = 1; } break;

               case "pic_ship4": if (count4 > 0) { cur_stat = 4; dir = 1; } break;

               case "pic_ship5": if (count4 > 0) { cur_stat = 4; dir = 2; } break;

               case "pic_ship6": if (count3 > 0) { cur_stat = 3; dir = 2; } break;

               case "pic_ship7": if (count2 > 0) { cur_stat = 2; dir = 2; } break;

               default: break;

           }

       }

       private void mouse_e(object sender, EventArgs e)

       {

           switch ((sender as PictureBox).Name.ToString())

           {

               case "pic_reset": (sender as PictureBox).Image = Properties.Resources.btn_Reset2; break;

               case "pic_auto": (sender as PictureBox).Image = Properties.Resources.btn_auto2; break;

           }

       }

       private void mouse_l(object sender, EventArgs e)

       {

           switch ((sender as PictureBox).Name.ToString())

           {

               case "pic_reset": (sender as PictureBox).Image = Properties.Resources.btn_Reset; break;

               case "pic_auto": (sender as PictureBox).Image = Properties.Resources.btn_auto; break;

           }

       }

       private void pic_reset_Click(object sender, EventArgs e)

       {

           int i, j;

           lbl1.Text = "x1";

           lbl2.Text = "x2";

           lbl3.Text = "x3";

           lbl4.Text = "x4";

           for (i = 1; i < 11; i++)

               for (j = 1; j < 11; j++)

               {

                   (Controls["p_a_" + i + j] as PictureBox).Tag = 0;

                   field_player[i, j] = 0;

               }

           count4 = 1;

           count3 = 2;

           count2 = 3;

           count1 = 4;

           ship_count_p = 0;

           draw_field("p_a_");

           btn_Battle.Visible = false;

       }

       private void pic_auto_Click(object sender, EventArgs e)

       {

           pic_reset_Click(sender, e);

           while (count1 != 0 || count2 != 0 || count3 != 0 || count4 != 0)

{

               pic_reset_Click(sender, e);

               auto_set("p_a_");

           }

           draw_field("p_a_");

       }

       private void mouse_enter_diff(object sender, EventArgs e)

       {

           switch ((sender as PictureBox).Name.ToString())

           {

               case "pic_easy": (sender as PictureBox).Image = Properties.Resources.btn_easy_2; break;

               case "pic_normal": (sender as PictureBox).Image = Properties.Resources.btn_normal_2; break;

               case "pic_hard": (sender as PictureBox).Image = Properties.Resources.btn_hard_2; break;

           }

       } //наведениенакнопкууровнясложности

       private void mouse_leave_diff(object sender, EventArgs e)

       {

           switch ((sender as PictureBox).Name.ToString())

           {

               case "pic_easy": (sender as PictureBox).Image = Properties.Resources.btn_easy; break;

               case "pic_normal": (sender as PictureBox).Image = Properties.Resources.btn_normal; break;

               case "pic_hard": (sender as PictureBox).Image = Properties.Resources.btn_hard; break;

           }

       } //выходизкнопкиуровнясложности

       private void mouse_click_diff(object sender, EventArgs e) //нажатиенакнопкууровнясложности

       {

           pic_easy.Visible = false;

           pic_normal.Visible = false;

           pic_hard.Visible = false;

           pic_reset.Visible = true;

           pic_auto.Visible = true;

           pic_chooseDiff.Visible = false;

           generate_field(30, 115, "p_a_");

           for (int i = 1; i <= 7; i++)

               Controls["pic_ship" + i].Visible = true;

           for (int i = 1; i <= 4; i++)

               Controls["lbl" + i].Visible = true;

           switch ((sender as PictureBox).Name.ToString())

           {

               case "pic_easy": difficult = 1; break;

               case "pic_normal": difficult = 2; break;

               case "pic_hard": difficult = 3; break;

           }

       }

       private void mouse_enter_stat(object sender, EventArgs e)

       {

           (sender as PictureBox).Image = Properties.Resources.btn_statistic2;

       }

       private void mouse_leave_stat(object sender, EventArgs e)

       {

           (sender as PictureBox).Image = Properties.Resources.btn_statistic;

       }

       private void mouse_click_stat(object sender, EventArgs e)

       {

           FrmStat.ShowDialog();

       }

   }

}

AI.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace SeaBattle

{

   public class AI

   {

       public int last_x;

       public int last_y;

       public int dir; //0 - none, 1 - horiz, 2 - vert

public int destr_in_proc; //идёт уничтожение корабля (для установки координат первого попадания)

public bool hit = false; //идётуничтожениекорабля

       bool turn = false; //ходИИ

       public int miss_count=0; //счётчикпромаховдлясложногоуровня

       public AI()

       {

           last_x = 0;

           last_y = 0;

           dir = 0;

           destr_in_proc = 0;

           hit = false;

       }

       public void set_turn(bool n)

       {

           turn = n;

       }

       public void set_last(int x, int y)

       {

           last_x = x;

           last_y = y;

       }

       public bool get_turn()

       {

           return turn;

       }

       public int[] select_dot_1(int[,] field)

       {

           int[] coord = new int[2];

           int x1, y1;

           Random rnd = new Random();

           turn = true;

           do

           {

               x1 = rnd.Next(1, 11); //x

               y1 = rnd.Next(1, 11); //y

           } while ((field[x1, y1] == 2 || field[x1, y1] == 3 || field[x1, y1] == 4));

           coord[0] = x1;

           coord[1] = y1;

           return coord;

       }

       public int[] select_dot_2_3(int[,] field, int diff)

       {

           int[] coord = new int[2];

           int x1, y1;

           Random rnd = new Random();

           turn = true;

           if (hit == false)

           {

               if (diff == 2)

               {

                   do

                   {

                       x1 = rnd.Next(1, 11); //x

                       y1 = rnd.Next(1, 11); //y

                   } while ((field[x1, y1] == 2 || field[x1, y1] == 3 || field[x1, y1] == 4));

                   coord[0] = x1;

                   coord[1] = y1;

                   return coord;

               }

               else

               {

                   if (miss_count < 2)

                   {

                       do

                       {

                           x1 = rnd.Next(1, 11); //x

                           y1 = rnd.Next(1, 11); //y

                       } while ((field[x1, y1] == 2 || field[x1, y1] == 3 || field[x1, y1] == 4));

                       miss_count++;

                   }

                   else

                   {

                       do

                       {

                           x1 = rnd.Next(1, 11); //x

                           y1 = rnd.Next(1, 11); //y

                       } while (field[x1, y1] != 1);

                       miss_count = 0;

                   }

                   coord[0] = x1;

                   coord[1] = y1;

                   return coord;

               }

           }

           else

           {

               switch (dir)

               {

                   case 0:

                       {

                           do

                           {

                               x1 = rnd.Next(-1, 2);

                               if (x1 == 0)

                               {

                                   y1 = rnd.Next(-1, 2);

                                   if ((last_x + x1 < 11) && (last_y + y1 < 11) && field[last_x + x1, last_y + y1] == 1)

                                       dir = 2;

                               }

                               else

                               {

                                   y1 = 0;

                                   if ((last_x + x1<11) && (last_y + y1<11) && field[last_x + x1, last_y + y1] == 1)

                                       dir = 1;

                               }

                               coord[0] = last_x + x1;

                               coord[1] = last_y + y1;

                           } while (coord[0] > 10 || coord[0] < 0 || coord[1] > 10 || coord[1] < 0 || field[coord[0], coord[1]] == 2 || field[coord[0], coord[1]] == 3 || field[coord[0], coord[1]] == 4);

break;

                       }

                   case 1:

                       { //корабль установлен вертикально

                           do

{

                               int i=1;

                               while (!((last_x + i < 11 && field[last_x + i, last_y] == 1) || (last_x - i > 0 && field[last_x - i, last_y] == 1)))

                                   i++;

                               do

                               {

                                   if (rnd.Next(0, 2) == 1)

                                       x1 = i;

                                   else x1 = -i;

                               } while ((last_x + x1) < 0 || (last_x + x1) > 10 || field[last_x + x1, last_y] != 1);

                               coord[0] = last_x + x1;

                               coord[1] = last_y;

                           } while (coord[0] > 10 || coord[0] < 0 || field[coord[0], coord[1]] == 2 || field[coord[0], coord[1]] == 3 || field[coord[0], coord[1]] == 4);

break;

                       }

                   case 2:

                       { //корабль установлен горизонтально

                           do

{

                               int i = 1;

                               while (!((last_y + i < 11 && field[last_x, last_y + i] == 1) || (last_y - i > 0 && field[last_x, last_y - i] == 1)))

                                   i++;

                               do

                               {

                                   if (rnd.Next(0, 2) == 1)

                                       y1 = i;

                                   else y1 = -i;

                               } while ((last_y + y1) < 0 || (last_y + y1) > 10 || field[last_x, last_y + y1] != 1);

                               coord[0] = last_x;

                               coord[1] = last_y + y1;

                           } while (coord[1] > 10 || coord[1] < 0 || field[coord[0], coord[1]] == 2 || field[coord[0], coord[1]] == 3 || field[coord[0], coord[1]] == 4);

                           break;

                       }

               }

               return coord;

           }

        }

     }

}

Ships.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace SeaBattle

{

   public class Ship

   {

       public struct squares_stat

       {

           public int x;

           public int y;

           public int stat;

       }

       public squares_stat[] sq = new squares_stat[4];

       private int n;

       public int destr;

       public Ship(int n)

       {

           this.n = n;

           this.destr = 0;

           for (int i = 0; i < n; i++)

               sq[i].stat = 1;

       }

       public int get_n()

       {

           return n;

       }

       public int[,] ship_check(int[,] field)

       {

          int destroyed=1;

          for (int i = 0; i < n; i++)

              if (sq[i].stat == 1)

                  destroyed = 0;

          if (destroyed == 1)

          {

              for (int i = 0; i < n; i++)

              {

                  field[sq[i].x, sq[i].y] = 4;

                  if ((sq[i].x + 1) < 11 && field[sq[i].x + 1, sq[i].y] == 6) //низ

                      field[sq[i].x + 1, sq[i].y] = 2;

                  if ((sq[i].x - 1) > 0 && field[sq[i].x - 1, sq[i].y] == 6) //верх

                      field[sq[i].x - 1, sq[i].y] = 2;

                  if ((sq[i].y + 1) < 11 && field[sq[i].x, sq[i].y + 1] == 6) //право

                      field[sq[i].x, sq[i].y + 1] = 2;

                  if ((sq[i].y - 1) > 0 && field[sq[i].x, sq[i].y - 1] == 6) //лево

                      field[sq[i].x, sq[i].y - 1] = 2;

                  if ((sq[i].x + 1) < 11 && (sq[i].y + 1) < 11 && field[sq[i].x + 1, sq[i].y + 1] == 6) //низ-право

                      field[sq[i].x + 1, sq[i].y + 1] = 2;

                  if ((sq[i].x + 1) < 11 && (sq[i].y - 1) > 0 && field[sq[i].x + 1, sq[i].y - 1] == 6) //низ-лево

                      field[sq[i].x + 1, sq[i].y - 1] = 2;

                  if ((sq[i].x - 1) > 0 && (sq[i].y + 1) < 11 && field[sq[i].x - 1, sq[i].y + 1] == 6) //верх-право

                      field[sq[i].x - 1, sq[i].y + 1] = 2;

                  if ((sq[i].x - 1) > 0 && (sq[i].y - 1) > 0 && field[sq[i].x - 1, sq[i].y - 1] == 6) //верх-лево

                      field[sq[i].x - 1, sq[i].y - 1] = 2;

              }

              destr = 1;

          }

          return field;

       }

   }

}

FormStatistic.cs

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

using System.IO;

namespace SeaBattle

{

   public partial class FormStatistic : Form

   {

       public FormStatistic()

       {

           InitializeComponent();

       }

       private void FormStatistic_Load(object sender, EventArgs e)

       {

           lbl_diff.Text = "";

           lbl_result.Text = "";

       }

       public void show_result(int button)

       {

           int[] stat = new int[6];

           StreamReader sr = new StreamReader("stat");

           for (int i = 0; i < 6; i++)

               stat[i] = Convert.ToInt32(sr.ReadLine());

           sr.Close();

           switch (button)

           {

               case 1:

{

lbl_diff.Text = "Уровень сложности: лёгкий";

lbl_result.Text = "Победигрока: " + stat[0].ToString() + "\n";

                       lbl_result.Text += "ПобедИИ: " + stat[1].ToString() + "\n";

break;

                   }

               case 2:

                   {

                       lbl_diff.Text = "Уровень сложности: средний";

lbl_result.Text = "Победигрока: " + stat[2].ToString() + "\n";

                       lbl_result.Text += "ПобедИИ: " + stat[3].ToString() + "\n";

break;

                   }

               case 3:

                   {

                       lbl_diff.Text = "Уровень сложности: высокий";

lbl_result.Text = "Победигрока: " + stat[4].ToString() + "\n";

                       lbl_result.Text += "ПобедИИ: " + stat[5].ToString() + "\n";

                       break;

                   }

           }

       }

       private void btn_easy_Click(object sender, EventArgs e)

       {

           show_result(1);

       }

       private void btn_medium_Click(object sender, EventArgs e)

       {

           show_result(2);

       }

       private void btn_hard_Click(object sender, EventArgs e)

       {

           show_result(3);

       }

       private void btn_reset_Click(object sender, EventArgs e)

       {

           StreamWriter sw = new StreamWriter("stat");

           for (int i = 0; i < 6; i++)

               sw.WriteLine("0");

           sw.Close();

           show_result(1);

       }

       private void btn_exit_Click(object sender, EventArgs e)

{

           this.Close();

       }

   }

}


 

А также другие работы, которые могут Вас заинтересовать

1835. КОНСТИТУЦИОННО-ПРАВОВОЕ РЕГУЛИРОВАНИЕ ПОЛИТИЧЕСКОГО УЧАСТИЯ ГРАЖДАН В ОСУЩЕСТВЛЕНИИ ГОСУДАРСТВЕННОЙ ВЛАСТИ 1.31 MB
  Взгляды на формы политического участия граждан в осуществлении государственной власти. Становление современного конституционного законодательства о формах политического участия граждан в осуществлении государственной власти. Тенденции развития и совершенствования российского конституционного законодательства о формах политического участия граждан в осуществлении государственной власти.
1836. ПЕДАГОГИЧЕСКИЕ УСЛОВИЯ ОБЕСПЕЧЕНИЯ КАЧЕСТВА ОБУЧЕНИЯ СТУДЕНТОВ ЭКСТЕРНАТА В ВУЗЕ 1.3 MB
  Теоретическое обоснование педагогических условий обеспечения качества обучения студентов экстерната. Апробация условий обеспечения качества подготовки экстернов в системе высшего образования. Экспериментальная проверка педагогических условий обеспечения качества подготовки специалистов в форме экстерната в вузе.
1837. ФЛОРА ПРИКАЛАУССКОГО ФЛОРИСТИЧЕСКОГО РАЙОНА (ЦЕНТРАЛЬНОЕ ПРЕДКАВКАЗЬЕ) И ЕЕ АНАЛИЗ 1.3 MB
  Физико-географическая характеристика Прикалаусского флористического района. Вопросы фитосозологии и перспективы использования. Конспект флоры Прикалаусского флористического района. Список редких, охраняемых и нуждающихся в охране видов Прикалаусского флористического района. Иллюстрации эндемичных и реликтовых видов флоры Прикалаусского флористического района, занесенные в Красную книгу Ставропольского края
1838. VBScript Scripting Reference 1.3 MB
  Working with the Properties Tables. ExportOptionsIllustrator. PDFSaveOptions. Running JavaScript based Action Manager code from VBScript. Appendix A: Event ID Codes.
1839. ПАРАЛЛЕЛИЗМ ИЗМЕНЕНИЙ ДЕРМАТОГЛИФИКИ, ЭНДОКРИННОГО И ПСИХИЧЕСКОГО СТАТУСА В ПОПУЛЯЦИИ ДЕТСКОГО НАСЕЛЕНИЯ, ПРОЖИВАЮЩЕГО В РАЙОНАХ С ВЫСОКОЙ АНТРОПОГЕННОЙ НАГРУЗКОЙ 1.3 MB
  Современное состояние окружающей среды (региональные аспекты). Генетические детерминанты формирования рельефа кожи пальцев рук и ладоней человека. Методика исследования кожного узора кисти человека. Методы исследования функционального состояния центральной нервной системы. Особенности эндокринного статуса подростков, проживающих в экологически неблагоприятных условиях.
1840. ПОВЫШЕНИЕ ЭФФЕКТИВНОСТИ СИСТЕМЫ УПРАВЛЕНИЯ ЗАПАСАМИ НА ОСНОВЕ ПРИМЕНЕНИЯ МЕТОДОВ ИНФОРМАЦИОННОЙ ПОДДЕРЖИ ПРИНЯТИЯ РЕШЕНИЙ 1.29 MB
  Анализ состояния и пути повышения эффективности систем управления запасами на машиностроительных предприятиях. Структуризация процессов управления и производственного процесса. Методика определения оптимального графика поступлений запасов. Применение разработанных методик и оценка эффективности их использования.
1841. ПРОИЗВОДСТВО И ВОСПРОИЗВОДСТВО ЗНАНИЯ: КОГНИТИВНО-АНТРОПОЛОГИЧЕСКИЙ АСПЕКТ 1.29 MB
  Производство и воспроизводство знания: когнитивно-антропологическая модель. Когнитивно-антропологические основания познания. Познание как проблема современной философии. Образование с позиций когнитивно-антропологического подхода.
1842. КОНЦЕПТОСФЕРА ВНУТРИСЕМЕЙНЫХ РОДОСЛОВНЫХ 1.29 MB
  Жанровая и языковая специфика внутрисемейных родословных. Художественные и публицистические реминисценции в языке внутрисемейных родословных. Специфика интертекстуальности. Система концептов, регулирующих жанр внутрисемейных родословных, и их лексическая объективация. Методика исследования частотности языковой объективации концептов и межконцептных связей. Математическое моделирование концептосферы внутрисемейных родословных. Результаты исследования.
1843. Основы маркетинга и современная маркетинговая концепция 1.4 MB
  Основные понятия маркетинга. Маркетинговая концепция. Используемые в маркетинге термины. Уровни маркетинга. Концепции маркетинговой деятельности организаций. Управленческий маркетинг должен показать свою рентабельность. Рыночные факторы, определяющие содержание маркетинг-микса. Основные продуктивные информационные легенды, используемые при проведении исследований конкурентов.