C#
Практическая работа
18 дек 2021
1 страниц

Выполнить задание

Задание для дистанционного обучения № 4. Коллекции. Работа с потоками.

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

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

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

Детали:
• Обеспечить в интерфейсе программы:
- возможность добавления/удаления объекта каждого типа в количестве нескольких единиц. В том числе, прямо во время боя. Это моделирует ситуацию, когда в бою в поле зрения робота динамически появляются и исчезают различные объекты: вражеские солдаты, танки, самолёты и пр.
- отображение списка объектов на поле боя.
- отображение текущего действия робота.
• Для хранения объектов использовать коллекции.
• Робот действует следующим образом в порядке убывания приоритета:
- Если на поле боя есть наш офицер, он его защищает
- Если на поле боя есть вражеский самолёт, дроид прячется
- Если на поле боя есть вражеский танк, робот его уничтожает
- Если на поле боя есть вражеский солдат, робот его уничтожает.
• Добавление/удаление объектов должно работать одновременно с работой дроида.
• Робот решает, что делать, и делает одно действие один раз в 2 секунды.

Логика робота и вся программа в целом может быть усложнена. Это будет оцениваться в виде дополнительных баллов.
Программа может быть написана как развитие программы по чтению описания видов объектов на поле боя из XML-файла (работа ДО2). Это тоже будет учитываться дополнительными баллами.



Методические указания:
Для хранения объектов напрашивается использование либо необобщённых коллекций ArrayList и Hashtable, либо обобщённой –Dictionary. В случае использования ArrayList вы можете в ней хранить несколько одинаковых элементов, например танков (ну и, наряду с ними, и другие объекты). В случае Hashtable и Dictionary – только один элемент одного типа (ключ), зато можно хранить количество этих элементов в значении ключа.
Пример создания коллекции:
Dictionary BattleFieldObjects = new Dictionary();
Пример добавления одного танка в коллекцию:
BattleFieldObjects.Add("Вражеский танк", 1)
Надо, однако, иметь в виду, что если танк(и) там уже есть, то надо считать их количество, увеличить на 1 и сохранить в коллекции новое значение для ключа “Вражеский танк”.
Дополнительно про работу с коллекциями смотрите в лекционном материале.
Рекомендация: Когда вы будете писать код для добавления солдата, самолёта, танка и пр.., вы увидите, что делаете одно и то же. Соответственно, хороший программист должен вынести добавление (и удаление) объекта в отдельный метод.

Для того чтобы пользователь (мог добавлять/удалять объекты) и робот могли действовать одновременно, следует одно из этих двух действий запустить в отдельном потоке. Для этого надо где-то создать метод, который отвечает за логику робота. Например:
private void DroidActons()
{
while () // Пока на поле боя есть объекты
{
// Уничтожаем, защищаем, прячемся,…
}
}
А когда пользователь нажимет кнопку “Активировать робота”, то этот метод должен запускаться в отдельном потоке:
private void buttonDroidStart_Click(object sender, EventArgs e)
{
DroidThrd = new Thread(DroidActons); // Создать поток
DroidThrd.Start(); // Запустить на исполнение
}
Всего-то и делов!
Подробнее о работе с потоками можно прочитать в книге Шилдта или на других ресурсах.
Ах да! Если закрыть программу до того, как робот выполнит все свои действия, то поток может остаться в памяти, что помешает перекомпилировать и вновь запустить программу. Придётся в диспетчере задач отыскивать соответствующий процесс и убивать его. Чтобы таких неприятностей не возникало, необходимо прописать уничтожение потока с нашим роботом в случае закрытия программы.
Метод, который вызывается в случае закрытия программы (когда пользователь наживает на крестик сверху справа окна), стандартно называется Dispose. Отыщите его с помощью поиска по всему проекту. И вставьте там команду для уничтожения потока: DroidThrd.Abort(); Однако, надо убедиться, что поток ещё умер сам. Для этого проверяем, что он не равен null:
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
if (DroidThrd != null) DroidThrd.Abort();
}
Т.е., в конце найденного вами метода Dispose надо вставить единственную строчку: if (DroidThrd != null) DroidThrd.Abort();.
Впрочем, иногда эта технология почему-то не срабатывает. Возможно, гораздо проще вам покажется сделать дочерний поток фоновым. Тогда при завершении основной программы, он автоматически будет уничтожен:
DroidThrd = new Thread(DroidActons); // Создать поток
DroidThrd.IsBackground = true; // Сделать поток фоновым
DroidThrd.Start(); // Запустить на исполнение

Kuznetsov Kuznetsov
1500 р