diff --git a/ProjectAirPlane/ProjectAirPlane.sln b/ProjectAirPlane/ProjectAirPlane.sln
index ba2feb3..d8185d7 100644
--- a/ProjectAirPlane/ProjectAirPlane.sln
+++ b/ProjectAirPlane/ProjectAirPlane.sln
@@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.8.34525.116
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectAirPlane", "ProjectAirPlane\ProjectAirPlane.csproj", "{36780227-CEDB-4504-AF69-0EB987304B89}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProjectAirPlane", "ProjectAirPlane\ProjectAirPlane.csproj", "{36780227-CEDB-4504-AF69-0EB987304B89}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/ProjectAirPlane/ProjectAirPlane/CollectionGenericObjects/AbstractCompany.cs b/ProjectAirPlane/ProjectAirPlane/CollectionGenericObjects/AbstractCompany.cs
new file mode 100644
index 0000000..5788d0b
--- /dev/null
+++ b/ProjectAirPlane/ProjectAirPlane/CollectionGenericObjects/AbstractCompany.cs
@@ -0,0 +1,118 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using ProjectAirPlane.Drawnings;
+
+namespace ProjectAirPlane.CollectionGenericObjects;
+
+public abstract class AbstractCompany
+{
+ ///
+ /// Размер места (ширина)
+ ///
+ protected readonly int _placeSizeWidth = 210;
+
+ ///
+ /// Размер места (высота)
+ ///
+ protected readonly int _placeSizeHeight = 80;
+
+ ///
+ /// Ширина окна
+ ///
+ protected readonly int _pictureWidth;
+
+ ///
+ /// Высота окна
+ ///
+ protected readonly int _pictureHeight;
+
+ ///
+ /// Коллекция автомобилей
+ ///
+ protected ICollectionGenericObjects? _collection = null;
+
+ ///
+ /// Вычисление максимального количества элементов, который можно разместить в окне
+ ///
+ private int GetMaxCount => _pictureWidth * _pictureHeight / (_placeSizeWidth * _placeSizeHeight);
+
+ ///
+ /// Конструктор
+ ///
+ /// Ширина окна
+ /// Высота окна
+ /// Коллекция автомобилей
+ public AbstractCompany(int picWidth, int picHeight, ICollectionGenericObjects collection)
+ {
+ _pictureWidth = picWidth;
+ _pictureHeight = picHeight;
+ _collection = collection;
+ _collection.SetMaxCount = GetMaxCount;
+ }
+
+ ///
+ /// Перегрузка оператора сложения для класса
+ ///
+ /// Компания
+ /// Добавляемый объект
+ ///
+ public static int operator +(AbstractCompany company, DrawningPlane plane)
+ {
+ return company._collection?.Insert(plane) ?? -1;
+ }
+
+ ///
+ /// Перегрузка оператора удаления для класса
+ ///
+ /// Компания
+ /// Номер удаляемого объекта
+ ///
+ public static DrawningPlane operator -(AbstractCompany company, int position)
+ {
+ return company._collection?.Remove(position) ?? null;
+ }
+
+ ///
+ /// Получение случайного объекта из коллекции
+ ///
+ ///
+ public DrawningPlane? GetRandomObject()
+ {
+ Random rnd = new();
+ return _collection?.Get(rnd.Next(GetMaxCount));
+ }
+
+ ///
+ /// Вывод всей коллекции
+ ///
+ ///
+ public Bitmap? Show()
+ {
+ Bitmap bitmap = new(_pictureWidth, _pictureHeight);
+ Graphics graphics = Graphics.FromImage(bitmap);
+ DrawBackgound(graphics);
+
+ SetObjectsPosition();
+ for (int i = 0; i < (_collection?.Count ?? 0); ++i)
+ {
+ DrawningPlane? obj = _collection?.Get(i);
+ obj?.DrawTransport(graphics);
+ }
+
+ return bitmap;
+ }
+
+ ///
+ /// Вывод заднего фона
+ ///
+ ///
+ protected abstract void DrawBackgound(Graphics g);
+
+ ///
+ /// Расстановка объектов
+ ///
+ protected abstract void SetObjectsPosition();
+}
diff --git a/ProjectAirPlane/ProjectAirPlane/CollectionGenericObjects/CollectionType.cs b/ProjectAirPlane/ProjectAirPlane/CollectionGenericObjects/CollectionType.cs
new file mode 100644
index 0000000..d88b9f1
--- /dev/null
+++ b/ProjectAirPlane/ProjectAirPlane/CollectionGenericObjects/CollectionType.cs
@@ -0,0 +1,22 @@
+namespace ProjectAirPlane.CollectionGenericObjects;
+
+///
+/// Тип коллекции
+///
+public enum CollectionType
+{
+ ///
+ /// Неопределено
+ ///
+ None = 0,
+
+ ///
+ /// Массив
+ ///
+ Massive = 1,
+
+ ///
+ /// Список
+ ///
+ List = 2
+}
\ No newline at end of file
diff --git a/ProjectAirPlane/ProjectAirPlane/CollectionGenericObjects/ICollectionGenericObjects.cs b/ProjectAirPlane/ProjectAirPlane/CollectionGenericObjects/ICollectionGenericObjects.cs
new file mode 100644
index 0000000..d609f17
--- /dev/null
+++ b/ProjectAirPlane/ProjectAirPlane/CollectionGenericObjects/ICollectionGenericObjects.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ProjectAirPlane.CollectionGenericObjects;
+
+public interface ICollectionGenericObjects
+ where T : class
+{
+ ///
+ /// Количество объектов в коллекции
+ ///
+ int Count { get; }
+
+ ///
+ /// Установка максимального количества элементов
+ ///
+ int SetMaxCount { set; }
+
+ ///
+ /// Добавление объекта в коллекцию
+ ///
+ /// Добавляемый объект
+ /// true - вставка прошла удачно, false - вставка не удалась
+ int Insert(T obj);
+
+ ///
+ /// Добавление объекта в коллекцию на конкретную позицию
+ ///
+ /// Добавляемый объект
+ /// Позиция
+ /// true - вставка прошла удачно, false - вставка не удалась
+ int Insert(T obj, int position);
+
+ ///
+ /// Удаление объекта из коллекции с конкретной позиции
+ ///
+ /// Позиция
+ /// true - удаление прошло удачно, false - удаление не удалось
+ T? Remove(int position);
+
+ ///
+ /// Получение объекта по позиции
+ ///
+ /// Позиция
+ /// Объект
+ T? Get(int position);
+}
diff --git a/ProjectAirPlane/ProjectAirPlane/CollectionGenericObjects/ListGenericObjects.cs b/ProjectAirPlane/ProjectAirPlane/CollectionGenericObjects/ListGenericObjects.cs
new file mode 100644
index 0000000..f356dfc
--- /dev/null
+++ b/ProjectAirPlane/ProjectAirPlane/CollectionGenericObjects/ListGenericObjects.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ProjectAirPlane.CollectionGenericObjects;
+
+public class ListGenericObjects : ICollectionGenericObjects
+ where T : class
+{
+ ///
+ /// Список объектов, которые храним
+ ///
+ private readonly List _collection;
+
+ ///
+ /// Максимально допустимое число объектов в списке
+ ///
+ private int _maxCount;
+
+ public int Count => _collection.Count;
+
+ public int SetMaxCount { set { if (value > 0) { _maxCount = value; } } }
+
+ ///
+ /// Конструктор
+ ///
+ public ListGenericObjects()
+ {
+ _collection = new();
+ }
+
+ public T? Get(int position)
+ {
+ // TODO проверка позиции
+ if (position >= Count || position < 0) return null;
+ return _collection[position];
+ }
+
+ public int Insert(T obj)
+ {
+ // TODO проверка, что не превышено максимальное количество элементов
+ // TODO вставка в конец набора
+ if (Count == _maxCount) return -1;
+ _collection.Add(obj);
+ return Count;
+ }
+
+ public int Insert(T obj, int position)
+ {
+ // TODO проверка, что не превышено максимальное количество элементов
+ // TODO проверка позиции
+ // TODO вставка по позиции
+ if (Count == _maxCount) return -1;
+ if (position >= Count || position < 0) return -1;
+ _collection.Insert(position, obj);
+ return position;
+ }
+
+ public T Remove(int position)
+ {
+ // TODO проверка позиции
+ // TODO удаление объекта из списка
+ if (position >= Count || position < 0) return null;
+ T obj = _collection[position];
+ _collection.RemoveAt(position);
+ return obj;
+ }
+}
diff --git a/ProjectAirPlane/ProjectAirPlane/CollectionGenericObjects/MassiveGenericObjects.cs b/ProjectAirPlane/ProjectAirPlane/CollectionGenericObjects/MassiveGenericObjects.cs
new file mode 100644
index 0000000..32c4e8f
--- /dev/null
+++ b/ProjectAirPlane/ProjectAirPlane/CollectionGenericObjects/MassiveGenericObjects.cs
@@ -0,0 +1,118 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ProjectAirPlane.CollectionGenericObjects;
+
+public class MassiveGenericObjects : ICollectionGenericObjects
+ where T : class
+{
+ ///
+ /// Массив объектов, которые храним
+ ///
+ private T?[] _collection;
+
+ public int Count => _collection.Length;
+
+ public int SetMaxCount
+ {
+ set
+ {
+ if (value > 0)
+ {
+ if (_collection.Length > 0)
+ {
+ Array.Resize(ref _collection, value);
+ }
+ else
+ {
+ _collection = new T?[value];
+ }
+ }
+ }
+ }
+
+ ///
+ /// Конструктор
+ ///
+ public MassiveGenericObjects()
+ {
+ _collection = Array.Empty();
+ }
+
+ public T? Get(int position)
+ {
+ // TODO проверка позиции
+ if (position >= _collection.Length || position < 0) return null;
+ return _collection[position];
+ }
+
+ public int Insert(T obj)
+ {
+ // TODO вставка в свободное место набора
+ int index = 0;
+ while (index < _collection.Length)
+ {
+ if (_collection[index] == null)
+ {
+ _collection[index] = obj;
+ return index;
+ }
+ ++index;
+ }
+ return -1;
+ }
+
+ public int Insert(T obj, int position)
+ {
+ // TODO проверка позиции
+ // TODO проверка, что элемент массива по этой позиции пустой, если нет, то
+ // ищется свободное место после этой позиции и идет вставка туда
+ // если нет после, ищем до
+ // TODO вставка
+ if (position >= _collection.Length || position < 0)
+ return -1;
+ if (_collection[position] == null)
+ {
+ _collection[position] = obj;
+ return position;
+ }
+ int index = position + 1;
+ while (index < _collection.Length)
+ {
+ if (_collection[index] == null)
+ {
+ _collection[index] = obj;
+ return index;
+ }
+ ++index;
+ }
+ index = position - 1;
+ while (index >= 0)
+ {
+ if (_collection[index] == null)
+ {
+ _collection[index] = obj;
+ return index;
+ }
+ --index;
+ }
+ return -1;
+ }
+
+ public T Remove(int position)
+ {
+ // TODO проверка позиции
+ // TODO удаление объекта из массива, присвоив элементу массива значение null
+ if (position >= _collection.Length || position < 0)
+ {
+ return null;
+ }
+
+ T obj = _collection[position];
+ _collection[position] = null;
+ return obj;
+ }
+}
diff --git a/ProjectAirPlane/ProjectAirPlane/CollectionGenericObjects/PlaneSharingService.cs b/ProjectAirPlane/ProjectAirPlane/CollectionGenericObjects/PlaneSharingService.cs
new file mode 100644
index 0000000..2b20d90
--- /dev/null
+++ b/ProjectAirPlane/ProjectAirPlane/CollectionGenericObjects/PlaneSharingService.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using ProjectAirPlane.Drawnings;
+
+namespace ProjectAirPlane.CollectionGenericObjects;
+
+public class PlaneSharingService : AbstractCompany
+{
+ public PlaneSharingService(int picWidth, int picHeight, ICollectionGenericObjects collection) : base(picWidth, picHeight, collection)
+ {
+ }
+
+ protected override void DrawBackgound(Graphics g)
+ {
+
+ int width = _pictureWidth / _placeSizeWidth;
+ int height = _pictureHeight / _placeSizeHeight;
+ Pen pen = new(Color.Black, 3);
+ for (int i = 0; i < width; i++)
+ {
+ for (int j = 0; j < height + 1; ++j)
+ {
+ g.DrawLine(pen, i * _placeSizeWidth, j * _placeSizeHeight, i * _placeSizeWidth + _placeSizeWidth - 5, j * _placeSizeHeight);
+ }
+ }
+ }
+
+ protected override void SetObjectsPosition()
+ {
+ int width = _pictureWidth / _placeSizeWidth;
+ int height = _pictureHeight / _placeSizeHeight;
+
+ int curWidth = width - 1;
+ int curHeight = 0;
+
+ for (int i = 0; i < (_collection?.Count ?? 0); i++)
+ {
+ if (_collection.Get(i) != null)
+ {
+ _collection.Get(i).SetPictureSize(_pictureWidth, _pictureHeight);
+ _collection.Get(i).SetPosition(_placeSizeWidth * curWidth + 15, curHeight * _placeSizeHeight + 3);
+ }
+ if (curWidth > 0)
+ curWidth--;
+ else
+ {
+ curWidth = width - 1;
+ curHeight++;
+ }
+ if (curHeight > height)
+ {
+ return;
+ }
+ }
+ }
+}
diff --git a/ProjectAirPlane/ProjectAirPlane/CollectionGenericObjects/StorageCollection.cs b/ProjectAirPlane/ProjectAirPlane/CollectionGenericObjects/StorageCollection.cs
new file mode 100644
index 0000000..d1b2c3d
--- /dev/null
+++ b/ProjectAirPlane/ProjectAirPlane/CollectionGenericObjects/StorageCollection.cs
@@ -0,0 +1,78 @@
+namespace ProjectAirPlane.CollectionGenericObjects;
+
+///
+/// Класс-хранилище коллекций
+///
+///
+public class StorageCollection
+ where T : class
+{
+ ///
+ /// Словарь (хранилище) с коллекциями
+ ///
+ readonly Dictionary> _storages;
+
+ ///
+ /// Возвращение списка названий коллекций
+ ///
+ public List Keys => _storages.Keys.ToList();
+
+ ///
+ /// Конструктор
+ ///
+ public StorageCollection()
+ {
+ _storages = new Dictionary>();
+ }
+
+ ///
+ /// Добавление коллекции в хранилище
+ ///
+ /// Название коллекции
+ /// тип коллекции
+ public void AddCollection(string name, CollectionType collectionType)
+ {
+ // TODO проверка, что name не пустой и нет в словаре записи с таким ключом
+ // TODO Прописать логику для добавления
+ if (!(collectionType == CollectionType.None) && !_storages.ContainsKey(name))
+ {
+ if (collectionType == CollectionType.List)
+ {
+ _storages.Add(name, new ListGenericObjects());
+ }
+ else if (collectionType == CollectionType.Massive)
+ {
+ _storages.Add(name, new MassiveGenericObjects());
+ }
+ }
+ }
+
+ ///
+ /// Удаление коллекции
+ ///
+ /// Название коллекции
+ public void DelCollection(string name)
+ {
+ // TODO Прописать логику для удаления коллекции
+ if (_storages.ContainsKey(name)) { _storages.Remove(name); }
+ }
+
+ ///
+ /// Доступ к коллекции
+ ///
+ /// Название коллекции
+ ///
+ public ICollectionGenericObjects? this[string name]
+ {
+ get
+ {
+ // TODO Продумать логику получения объекта
+ if (_storages.ContainsKey(name))
+ {
+ return _storages[name];
+ }
+ return null;
+ }
+ }
+
+}
diff --git a/ProjectAirPlane/ProjectAirPlane/Drawnings/DirectionType.cs b/ProjectAirPlane/ProjectAirPlane/Drawnings/DirectionType.cs
new file mode 100644
index 0000000..ebe8ff4
--- /dev/null
+++ b/ProjectAirPlane/ProjectAirPlane/Drawnings/DirectionType.cs
@@ -0,0 +1,32 @@
+namespace ProjectAirPlane.Drawnings;
+
+///
+/// Направление перемещения
+///
+public enum DirectionType
+{
+ ///
+ /// Неизвестное направление
+ ///
+ Unknow = -1,
+
+ ///
+ /// Вверх
+ ///
+ Up = 1,
+
+ ///
+ /// Вниз
+ ///
+ Down = 2,
+
+ ///
+ /// Влево
+ ///
+ Left = 3,
+
+ ///
+ /// Вправо
+ ///
+ Right = 4
+}
\ No newline at end of file
diff --git a/ProjectAirPlane/ProjectAirPlane/Drawnings/DrawningAirPlane.cs b/ProjectAirPlane/ProjectAirPlane/Drawnings/DrawningAirPlane.cs
new file mode 100644
index 0000000..5b24d56
--- /dev/null
+++ b/ProjectAirPlane/ProjectAirPlane/Drawnings/DrawningAirPlane.cs
@@ -0,0 +1,83 @@
+using ProjectAirPlane.Entites;
+
+namespace ProjectAirPlane.Drawnings;
+
+///
+/// Класс, отвечающий за прорисовку и перемещение объекта-сущности
+///
+public class DrawningAirPlane : DrawningPlane
+{
+
+ ///
+ /// Конструктор
+ ///
+ /// Скорость
+ /// Вес
+ /// Основной цвет
+ /// Дополнительный цвет
+ /// Признак наличия обвеса
+ /// Признак наличия антикрыла
+ /// Признак наличия гоночной полосы
+ public DrawningAirPlane(int speed, double weight, Color bodyColor, Color additionalColor, bool radar, bool dopBak, bool chassi) : base(195, 70)
+ {
+ EntityPlane = new EntityAirPlane(speed, weight, bodyColor, additionalColor, radar, dopBak, chassi);
+
+
+ }
+
+
+ public override void DrawTransport(Graphics g)
+ {
+ if (EntityPlane == null || EntityPlane is not EntityAirPlane airPlane || !_startPosX.HasValue || !_startPosY.HasValue)
+ {
+ return;
+ }
+ Pen pen = new(Color.Black);
+ Brush additionalBrush = new SolidBrush(EntityPlane.BodyColor);
+
+ if (airPlane.Chassi)
+ {
+ //шасси
+ g.DrawLine(pen, _startPosX.Value + 50, _startPosY.Value + 55, _startPosX.Value + 50, _startPosY.Value + 70);
+ g.DrawLine(pen, _startPosX.Value + 150, _startPosY.Value + 55, _startPosX.Value + 150, _startPosY.Value + 70);
+ g.FillEllipse(additionalBrush, _startPosX.Value + 40, _startPosY.Value + 65, 10, 10);
+ g.FillEllipse(additionalBrush, _startPosX.Value + 50, _startPosY.Value + 65, 10, 10);
+ g.FillEllipse(additionalBrush, _startPosX.Value + 145, _startPosY.Value + 65, 10, 10);
+
+ }
+
+
+ base.DrawTransport(g);
+
+
+
+ if (airPlane.DopBak)
+ {
+ //бак
+ g.FillEllipse(additionalBrush, _startPosX.Value, _startPosY.Value + 45, 40, 20);
+ g.DrawEllipse(pen, _startPosX.Value, _startPosY.Value + 45, 40, 20);
+
+ }
+
+ if (airPlane.Radar)
+ {
+ //радар
+ g.DrawLine(pen, _startPosX.Value + 60, _startPosY.Value + 25, _startPosX.Value + 60, _startPosY.Value + 15);
+ g.DrawLine(pen, _startPosX.Value + 60, _startPosY.Value + 15, _startPosX.Value + 67, _startPosY.Value + 11);
+ Point point7 = new Point(_startPosX.Value + 60, _startPosY.Value + 15);
+ Point point8 = new Point(_startPosX.Value + 60, _startPosY.Value + 5);
+ Point point9 = new Point(_startPosX.Value + 70, _startPosY.Value + 25);
+ Point[] curvePoints3 =
+ {
+ point7,
+ point8,
+ point9,
+ };
+ g.FillPolygon(additionalBrush, curvePoints3);
+
+ }
+
+ }
+}
+
+
diff --git a/ProjectAirPlane/ProjectAirPlane/Drawnings/DrawningPlane.cs b/ProjectAirPlane/ProjectAirPlane/Drawnings/DrawningPlane.cs
new file mode 100644
index 0000000..ffcadd5
--- /dev/null
+++ b/ProjectAirPlane/ProjectAirPlane/Drawnings/DrawningPlane.cs
@@ -0,0 +1,262 @@
+using ProjectAirPlane.Entites;
+
+namespace ProjectAirPlane.Drawnings;
+
+public class DrawningPlane
+{
+ ///
+ /// Класс-сущность
+ ///
+ public EntityPlane? EntityPlane { get; protected set; }
+
+ ///
+ /// Ширина окна
+ ///
+ private int? _pictureWidth;
+
+ ///
+ /// Высота окна
+ ///
+ private int? _pictureHeight;
+
+ ///
+ /// Левая координата прорисовки автомобиля
+ ///
+ protected int? _startPosX;
+
+ ///
+ /// Верхняя кооридната прорисовки автомобиля
+ ///
+ protected int? _startPosY;
+
+ ///
+ /// Ширина прорисовки самолёта
+ ///
+ private readonly int _drawningAirPlaneWidth = 195;
+
+ ///
+ /// Высота прорисовки самолёта
+ ///
+ private readonly int _drawningAirPlaneHeight = 70;
+
+ ///
+ /// Координата X объекта
+ ///
+ public int? GetPosX => _startPosX;
+
+ ///
+ /// Координата Y объекта
+ ///
+ public int? GetPosY => _startPosY;
+
+ ///
+ /// Ширина объекта
+ ///
+ public int GetWidth => _drawningAirPlaneWidth;
+
+ ///
+ /// Высота объекта
+ ///
+ public int GetHeight => _drawningAirPlaneHeight;
+
+ ///
+ /// Пустой конструктор
+ ///
+ private DrawningPlane()
+ {
+ _pictureWidth = null;
+ _pictureHeight = null;
+ _startPosX = null;
+ _startPosY = null;
+ }
+
+ ///
+ /// Конструктор
+ ///
+ /// Скорость
+ /// Вес
+ /// Основной цвет
+
+ public DrawningPlane(int speed, double weight, Color bodyColor) : this()
+ {
+
+ EntityPlane = new EntityPlane(speed, weight, bodyColor);
+
+ }
+
+ ///
+ /// Конструктор для наследования
+ ///
+ /// Ширина прорисовки самолёта
+ /// Высота прорисовки самолёта
+
+
+ protected DrawningPlane(int drawningPlaneWidth, int drawningPlaneHeight) : this()
+ {
+ _drawningAirPlaneWidth = drawningPlaneWidth;
+ _drawningAirPlaneHeight = drawningPlaneHeight;
+
+ }
+
+
+ ///
+ /// Установка границ поля
+ ///
+ /// Ширина поля
+ /// Высота поля
+ /// true - границы заданы, false - проверка не пройдена, нельзя разместить объект в этих размерах
+ public bool SetPictureSize(int width, int height)
+ {
+ // TODO проверка, что объект "влезает" в размеры поля
+
+ if (_drawningAirPlaneWidth > width || _drawningAirPlaneHeight > height)
+ {
+ return false;
+ }
+
+ _pictureWidth = width;
+ _pictureHeight = height;
+ if (_startPosX.HasValue || _startPosY.HasValue)
+ {
+ if (_startPosX + _drawningAirPlaneWidth > _pictureWidth)
+ {
+ _startPosX = _pictureWidth - _drawningAirPlaneWidth;
+ }
+ else if (_startPosX < 0) _startPosX = 0;
+ if (_startPosY + _drawningAirPlaneHeight > _pictureHeight)
+ {
+ _startPosY = _pictureHeight - _drawningAirPlaneHeight;
+ }
+ else if (_startPosY < 0) _startPosY = 0;
+ }
+ return true;
+ }
+
+ ///
+ /// Установка позиции
+ ///
+ /// Координата X
+ /// Координата Y
+ public void SetPosition(int x, int y)
+ {
+ if (!_pictureHeight.HasValue || !_pictureWidth.HasValue)
+ {
+ return;
+ }
+
+ // TODO если при установке объекта в эти координаты, он будет "выходить" за границы формы
+
+ if (x + _drawningAirPlaneWidth >= _pictureWidth || y + _drawningAirPlaneHeight >= _pictureHeight)
+ {
+ x = y = 10;
+ _startPosX = x;
+ _startPosY = y;
+ }
+ // то надо изменить координаты, чтобы он оставался в этих границах
+ _startPosX = x;
+ _startPosY = y;
+ }
+
+ ///
+ /// Изменение направления перемещения
+ ///
+ /// Направление
+ /// true - перемещене выполнено, false - перемещение невозможно
+ public bool MoveTransport(DirectionType direction)
+ {
+ if (EntityPlane == null || !_startPosX.HasValue || !_startPosY.HasValue)
+ {
+ return false;
+ }
+
+ switch (direction)
+ {
+ //влево
+ case DirectionType.Left:
+ if (_startPosX.Value - EntityPlane.Step > 0)
+ {
+ _startPosX -= (int)EntityPlane.Step;
+ }
+ return true;
+ //вверх
+ case DirectionType.Up:
+ if (_startPosY.Value - EntityPlane.Step > 0)
+ {
+ _startPosY -= (int)EntityPlane.Step;
+ }
+ return true;
+ // вправо
+ case DirectionType.Right:
+ //TODO прописать логику сдвига вправо
+ if (_startPosX + EntityPlane.Step + _drawningAirPlaneWidth < _pictureWidth)
+ {
+ _startPosX += (int)EntityPlane.Step;
+ }
+ return true;
+ //вниз
+ case DirectionType.Down:
+ //TODO прописать логику сдвига ввниз
+ if (_startPosY + EntityPlane.Step + _drawningAirPlaneHeight < _pictureHeight)
+ {
+ _startPosY += (int)EntityPlane.Step;
+ }
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ ///
+ /// Прорисовка объекта
+ ///
+ ///
+ public virtual void DrawTransport(Graphics g)
+ {
+ if (EntityPlane == null || !_startPosX.HasValue || !_startPosY.HasValue)
+ {
+ return;
+ }
+
+ Pen pen = new(Color.Black);
+ Brush additionalBrush = new SolidBrush(EntityPlane.BodyColor);
+
+
+ //шасси
+ g.DrawLine(pen, _startPosX.Value + 50, _startPosY.Value + 55, _startPosX.Value + 50, _startPosY.Value + 70);
+ g.DrawLine(pen, _startPosX.Value + 150, _startPosY.Value + 55, _startPosX.Value + 150, _startPosY.Value + 70);
+ g.FillEllipse(additionalBrush, _startPosX.Value + 40, _startPosY.Value + 65, 10, 10);
+ g.FillEllipse(additionalBrush, _startPosX.Value + 50, _startPosY.Value + 65, 10, 10);
+ g.FillEllipse(additionalBrush, _startPosX.Value + 145, _startPosY.Value + 65, 10, 10);
+ // корпус
+ Brush br = new SolidBrush(EntityPlane.BodyColor);
+ g.DrawRectangle(pen, _startPosX.Value, _startPosY.Value + 25, 170, 30);
+ g.FillRectangle(br, _startPosX.Value, _startPosY.Value + 25, 170, 30);
+ // бак
+ Brush blackBrush = new SolidBrush(Color.Black);
+ g.FillEllipse(blackBrush, _startPosX.Value + 75, _startPosY.Value + 30, 50, 10);
+ // нос самолёта
+ Pen blackPen = new Pen(Color.Black, 2);
+ Brush blueBrush = new SolidBrush(Color.LightBlue);
+ Point point1 = new Point(_startPosX.Value + 170, _startPosY.Value + 25);
+ Point point2 = new Point(_startPosX.Value + 200, _startPosY.Value + 40);
+ Point point3 = new Point(_startPosX.Value + 170, _startPosY.Value + 55);
+ Point[] curvePoints =
+ {
+ point1,
+ point2,
+ point3,
+ };
+ g.FillPolygon(blueBrush, curvePoints);
+ g.DrawPolygon(blackPen, curvePoints);
+ g.DrawLine(blackPen, _startPosX.Value + 170, _startPosY.Value + 40, _startPosX.Value + 200, _startPosY.Value + 40);
+ // хвост
+ Brush bw = new SolidBrush(EntityPlane.BodyColor);
+ g.FillPolygon(bw, new Point[]
+ {
+ new Point((int) _startPosX, (int) _startPosY + 40 ), new Point((int) _startPosX + 80, (int) _startPosY + 30),
+ new Point((int) _startPosX, (int) _startPosY), new Point((int) _startPosX , (int) _startPosY + 40),
+ }
+ );
+ }
+}
+
diff --git a/ProjectAirPlane/ProjectAirPlane/Entites/EntityAirPlane.cs b/ProjectAirPlane/ProjectAirPlane/Entites/EntityAirPlane.cs
new file mode 100644
index 0000000..c560690
--- /dev/null
+++ b/ProjectAirPlane/ProjectAirPlane/Entites/EntityAirPlane.cs
@@ -0,0 +1,52 @@
+namespace ProjectAirPlane.Entites;
+
+///
+/// Класс-сущность "Спортивный самолёт"
+///
+public class EntityAirPlane : EntityPlane
+{
+ ///
+ /// Дополнительный цвет (для опциональных элементов)
+ ///
+ public Color AdditionalColor { get; private set; }
+
+ ///
+ /// Признак (опция) наличия обвеса
+ ///
+ public bool Radar { get; private set; }
+
+ ///
+ /// Признак (опция) наличия антикрыла
+ ///
+ public bool DopBak { get; private set; }
+
+ ///
+ /// Признак (опция) наличия гоночной полосы
+ ///
+ public bool Chassi { get; private set; }
+
+ ///
+ /// Шаг перемещения автомобиля
+ ///
+
+
+ ///
+ /// Инициализация полей объекта-класса спортивного автомобиля
+ ///
+ /// Скорость
+ /// Вес автомобиля
+ /// Основной цвет
+ /// Дополнительный цвет
+ /// Признак наличия обвеса
+ /// Признак наличия антикрыла
+ /// Признак наличия гоночной полосы
+ public EntityAirPlane(int speed, double weight, Color bodyColor, Color additionalColor, bool radar, bool dopBak, bool chassi) : base(speed, weight, bodyColor)
+ {
+
+ AdditionalColor = additionalColor;
+ Radar = radar;
+ DopBak = dopBak;
+ Chassi = chassi;
+
+ }
+}
\ No newline at end of file
diff --git a/ProjectAirPlane/ProjectAirPlane/Entites/EntityPlane.cs b/ProjectAirPlane/ProjectAirPlane/Entites/EntityPlane.cs
new file mode 100644
index 0000000..5b0f796
--- /dev/null
+++ b/ProjectAirPlane/ProjectAirPlane/Entites/EntityPlane.cs
@@ -0,0 +1,43 @@
+namespace ProjectAirPlane.Entites;
+
+///
+/// Класс-сущность "Обычный самолёт"
+///
+public class EntityPlane
+{
+ ///
+ /// Скорость
+ ///
+ public int Speed { get; private set; }
+
+ ///
+ /// Вес
+ ///
+ public double Weight { get; private set; }
+
+ ///
+ /// Основной цвет
+ ///
+ public Color BodyColor { get; private set; }
+
+ ///
+ /// Шаг перемещения автомобиля
+ ///
+ public double Step => Speed * 100 / Weight;
+
+ ///
+ /// Конструктор сущности
+ ///
+ /// Скорость
+ /// Вес автомобиля
+ /// Основной цвет
+
+ public EntityPlane(int speed, double weight, Color bodyColor)
+ {
+ Speed = speed;
+ Weight = weight;
+ BodyColor = bodyColor;
+
+
+ }
+}
diff --git a/ProjectAirPlane/ProjectAirPlane/Form1.Designer.cs b/ProjectAirPlane/ProjectAirPlane/Form1.Designer.cs
deleted file mode 100644
index be1a087..0000000
--- a/ProjectAirPlane/ProjectAirPlane/Form1.Designer.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-namespace ProjectAirPlane
-{
- partial class Form1
- {
- ///
- /// Required designer variable.
- ///
- private System.ComponentModel.IContainer components = null;
-
- ///
- /// Clean up any resources being used.
- ///
- /// true if managed resources should be disposed; otherwise, false.
- protected override void Dispose(bool disposing)
- {
- if (disposing && (components != null))
- {
- components.Dispose();
- }
- base.Dispose(disposing);
- }
-
- #region Windows Form Designer generated code
-
- ///
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- ///
- private void InitializeComponent()
- {
- this.components = new System.ComponentModel.Container();
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Text = "Form1";
- }
-
- #endregion
- }
-}
diff --git a/ProjectAirPlane/ProjectAirPlane/Form1.cs b/ProjectAirPlane/ProjectAirPlane/Form1.cs
deleted file mode 100644
index 7d12854..0000000
--- a/ProjectAirPlane/ProjectAirPlane/Form1.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace ProjectAirPlane
-{
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/ProjectAirPlane/ProjectAirPlane/FormAirPlane.Designer.cs b/ProjectAirPlane/ProjectAirPlane/FormAirPlane.Designer.cs
new file mode 100644
index 0000000..42ee3eb
--- /dev/null
+++ b/ProjectAirPlane/ProjectAirPlane/FormAirPlane.Designer.cs
@@ -0,0 +1,147 @@
+namespace ProjectAirPlane
+{
+ partial class FormAirPlane
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormAirPlane));
+ pictureBoxAirPlane = new PictureBox();
+ buttonLeft = new Button();
+ buttonUp = new Button();
+ buttonDown = new Button();
+ buttonRight = new Button();
+ comboBoxStrategy = new ComboBox();
+ buttonStrategyStepS = new Button();
+ ((System.ComponentModel.ISupportInitialize)pictureBoxAirPlane).BeginInit();
+ SuspendLayout();
+ //
+ // pictureBoxAirPlane
+ //
+ pictureBoxAirPlane.Dock = DockStyle.Fill;
+ pictureBoxAirPlane.Location = new Point(0, 0);
+ pictureBoxAirPlane.Name = "pictureBoxAirPlane";
+ pictureBoxAirPlane.Size = new Size(749, 523);
+ pictureBoxAirPlane.TabIndex = 0;
+ pictureBoxAirPlane.TabStop = false;
+ //
+ // buttonLeft
+ //
+ buttonLeft.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
+ buttonLeft.BackgroundImage = (Image)resources.GetObject("buttonLeft.BackgroundImage");
+ buttonLeft.BackgroundImageLayout = ImageLayout.Stretch;
+ buttonLeft.Location = new Point(613, 476);
+ buttonLeft.Name = "buttonLeft";
+ buttonLeft.Size = new Size(35, 35);
+ buttonLeft.TabIndex = 2;
+ buttonLeft.UseVisualStyleBackColor = true;
+ buttonLeft.Click += ButtonMove_Click;
+ //
+ // buttonUp
+ //
+ buttonUp.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
+ buttonUp.BackgroundImage = (Image)resources.GetObject("buttonUp.BackgroundImage");
+ buttonUp.BackgroundImageLayout = ImageLayout.Stretch;
+ buttonUp.Location = new Point(654, 435);
+ buttonUp.Name = "buttonUp";
+ buttonUp.Size = new Size(35, 35);
+ buttonUp.TabIndex = 3;
+ buttonUp.UseVisualStyleBackColor = true;
+ buttonUp.Click += ButtonMove_Click;
+ //
+ // buttonDown
+ //
+ buttonDown.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
+ buttonDown.BackgroundImage = (Image)resources.GetObject("buttonDown.BackgroundImage");
+ buttonDown.BackgroundImageLayout = ImageLayout.Stretch;
+ buttonDown.Location = new Point(654, 476);
+ buttonDown.Name = "buttonDown";
+ buttonDown.Size = new Size(35, 35);
+ buttonDown.TabIndex = 4;
+ buttonDown.UseVisualStyleBackColor = true;
+ buttonDown.Click += ButtonMove_Click;
+ //
+ // buttonRight
+ //
+ buttonRight.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
+ buttonRight.BackgroundImage = (Image)resources.GetObject("buttonRight.BackgroundImage");
+ buttonRight.BackgroundImageLayout = ImageLayout.Stretch;
+ buttonRight.Location = new Point(695, 476);
+ buttonRight.Name = "buttonRight";
+ buttonRight.Size = new Size(35, 35);
+ buttonRight.TabIndex = 5;
+ buttonRight.UseVisualStyleBackColor = true;
+ buttonRight.Click += ButtonMove_Click;
+ //
+ // comboBoxStrategy
+ //
+ comboBoxStrategy.DropDownStyle = ComboBoxStyle.DropDownList;
+ comboBoxStrategy.FormattingEnabled = true;
+ comboBoxStrategy.Items.AddRange(new object[] { "К центру", "К краю" });
+ comboBoxStrategy.Location = new Point(628, 12);
+ comboBoxStrategy.Name = "comboBoxStrategy";
+ comboBoxStrategy.Size = new Size(121, 23);
+ comboBoxStrategy.TabIndex = 7;
+ //
+ // buttonStrategyStepS
+ //
+ buttonStrategyStepS.Location = new Point(654, 41);
+ buttonStrategyStepS.Name = "buttonStrategyStepS";
+ buttonStrategyStepS.Size = new Size(75, 23);
+ buttonStrategyStepS.TabIndex = 8;
+ buttonStrategyStepS.Text = "Шаг";
+ buttonStrategyStepS.UseVisualStyleBackColor = true;
+ buttonStrategyStepS.Click += ButtonStrategyStep_Click;
+ //
+ // FormAirPlane
+ //
+ AutoScaleDimensions = new SizeF(7F, 15F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(749, 523);
+ Controls.Add(buttonStrategyStepS);
+ Controls.Add(comboBoxStrategy);
+ Controls.Add(buttonRight);
+ Controls.Add(buttonDown);
+ Controls.Add(buttonUp);
+ Controls.Add(buttonLeft);
+ Controls.Add(pictureBoxAirPlane);
+ Name = "FormAirPlane";
+ Text = "Спортивный автомобиль";
+ ((System.ComponentModel.ISupportInitialize)pictureBoxAirPlane).EndInit();
+ ResumeLayout(false);
+ }
+
+ #endregion
+
+ private PictureBox pictureBoxAirPlane;
+ private Button buttonLeft;
+ private Button buttonUp;
+ private Button buttonDown;
+ private Button buttonRight;
+ private ComboBox comboBoxStrategy;
+ private Button buttonStrategyStepS;
+ }
+}
\ No newline at end of file
diff --git a/ProjectAirPlane/ProjectAirPlane/FormAirPlane.cs b/ProjectAirPlane/ProjectAirPlane/FormAirPlane.cs
new file mode 100644
index 0000000..91510ac
--- /dev/null
+++ b/ProjectAirPlane/ProjectAirPlane/FormAirPlane.cs
@@ -0,0 +1,133 @@
+using ProjectAirPlane.Drawnings;
+using ProjectAirPlane.MovementStrategy;
+
+
+namespace ProjectAirPlane;
+///
+/// ""
+///
+public partial class FormAirPlane : Form
+{
+ ///
+ /// -
+ ///
+ private DrawningPlane? _drawningPlane;
+
+ ///
+ ///
+ ///
+ private AbstractStrategy? _strategy;
+
+ public DrawningPlane SetPlane
+ {
+ set
+ {
+ _drawningPlane = value;
+ _drawningPlane.SetPictureSize(pictureBoxAirPlane.Width, pictureBoxAirPlane.Height);
+ comboBoxStrategy.Enabled = true;
+ _strategy = null;
+ Draw();
+ }
+ }
+
+ ///
+ ///
+ ///
+ public FormAirPlane()
+ {
+ InitializeComponent();
+ _strategy = null;
+ }
+
+ ///
+ ///
+ ///
+ private void Draw()
+ {
+ if (_drawningPlane == null)
+ {
+ return;
+ }
+
+ Bitmap bmp = new(pictureBoxAirPlane.Width, pictureBoxAirPlane.Height);
+ Graphics gr = Graphics.FromImage(bmp);
+ _drawningPlane.DrawTransport(gr);
+ pictureBoxAirPlane.Image = bmp;
+ }
+
+ ///
+ /// ( )
+ ///
+ ///
+ ///
+ private void ButtonMove_Click(object sender, EventArgs e)
+ {
+ if (_drawningPlane == null)
+ {
+ return;
+ }
+
+ string name = ((Button)sender)?.Name ?? string.Empty;
+ bool result = false;
+ switch (name)
+ {
+ case "buttonUp":
+ result = _drawningPlane.MoveTransport(DirectionType.Up);
+ break;
+ case "buttonDown":
+ result = _drawningPlane.MoveTransport(DirectionType.Down);
+ break;
+ case "buttonLeft":
+ result = _drawningPlane.MoveTransport(DirectionType.Left);
+ break;
+ case "buttonRight":
+ result = _drawningPlane.MoveTransport(DirectionType.Right);
+ break;
+ }
+
+ if (result)
+ {
+ Draw();
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ private void ButtonStrategyStep_Click(object sender, EventArgs e)
+ {
+ if (_drawningPlane == null) return;
+
+ if (comboBoxStrategy.Enabled)
+ {
+ _strategy = comboBoxStrategy.SelectedIndex switch
+ {
+ 0 => new MoveToCenter(),
+ 1 => new MoveToBorder(),
+ _ => null,
+ };
+ if (_strategy == null)
+ {
+ return;
+ }
+ _strategy.SetData(new MoveablePlane(_drawningPlane), pictureBoxAirPlane.Width, pictureBoxAirPlane.Height);
+ }
+
+ if (_strategy == null)
+ {
+ return;
+ }
+
+ comboBoxStrategy.Enabled = false;
+ _strategy.MakeStep();
+ Draw();
+
+ if (_strategy.GetStatus() == StrategyStatus.Finish)
+ {
+ comboBoxStrategy.Enabled = true;
+ _strategy = null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/ProjectAirPlane/ProjectAirPlane/FormAirPlane.resx b/ProjectAirPlane/ProjectAirPlane/FormAirPlane.resx
new file mode 100644
index 0000000..f8be0c1
--- /dev/null
+++ b/ProjectAirPlane/ProjectAirPlane/FormAirPlane.resx
@@ -0,0 +1,555 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+
+ 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
+ AAAASUVORK5CYII=
+
+
+
+
+ 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
+ CgAbxRC61SgAoACwUQyhW40CAAoAG8UQutUoAKAAsFEMoVuNAgAKABvFELrVKACgALBRDKFbjQIACgAb
+ xRC61SgAoACwUQyhW40CAAoAG8UQutUoAKAAsFEMoVuNAgAKABvFELrVKACgALBRDKFbjQIACgAbxRC6
+ 1SgAoACwUQyhW40CAAoAG8UQutUoAKAAsFEMoVuNAgAKABvFELrVKACgALBRDKFbjQIACgAbxRC61SgA
+ oACwUQyhW40CAAoAG8UQutUoAKAAsFEMoVuNAgAKABvFELrVKACgALBRDKFbjQIACgAbxRC61SgAoACw
+ UQyhW40CAAoAG8UQutUoAKAAsFEMoVuNAgAKABvFELrVKACgALBRDKFbjQIACgAbxRC61SgAoACwUQyh
+ W40CAAoAG8UQutUoAKAAsFEMoVuNAgAKABvFELrVKACgALBRDKFbjQIACgAbxRC61SgAoACwUQyhW40C
+ AAoAG8UQutUoAKAAsFEMoVuNAgAKABvFELrVKACgALBRDKFbjQIACgAbxRC61SgAoACwUQyhW40CAAoA
+ G8UQutUoAKAAsFEMoVuNAgAKABvFELrVKACgALBRDKFbjQIACgAbxRC61SgAoACwUQyhW40CAAoAG8UQ
+ utUoAKAAsFEMoVuNAgAKABvFELrVKACgALBRDKFbjQIACgAbxRC61SgAoACwUQyhW40CAAoAG8UQutUo
+ AKAAsFEMoVuNAgAKABvFELrVKACgALBRDKFbjQIACgAbxRC61SgAoACwUQyhW40CAAoAG8UQutUoAKAA
+ sFEMoVuNAgAKABvFELrVKACgALBRDKFbjQIACgAbxRC61SgAoACwUQyhW40CAAoAG8UQutUoAKAAsFEM
+ oVuNAgAKABvFELrVKACgALBRDKFbjQIACgAbxRC61SgAoACwUQyhW40CAAoAG8UQutUoAKAAsFEMoVuN
+ AgAKABvFELrVKACgALBRDKFbjQIACgAbxRC61SgAoACwUQyhW40CAAoAG8UQutUoAKAAsFEMoVuNAgAK
+ ABvFELrVKACgALBRDKFbjQIACgAbxRC61SgAoACwUQyhW40CAAoAG8UQutUoAKAAsFEMoVuNAgAKABvF
+ ELrVKACgALBRDKFbjQIACgAbxRC61SgAoACwUQyhW40CAAoAG8UQutUoAKAAsFEMoVuNAgAKABvFELrV
+ KACgALBRDKFbjQIACgAbxRC61SgAoACwUQyhW40CAAoAG8UQutUoAKAAsFEMoVuNAgAKABvFELrVKACg
+ ALBRDKFbjQIACgAbxRC61SgAoACwUQyhW40CAAoAG8UQutUoAKAAsFEMoVuNAgAKABvFELrVKACgALBR
+ DKFbjQIACgAbxRC61SgAoACwUQyhW40CAAoAG8UQutUoAKAAsFEMoVuNAgAKABvFELrVKACgALBRDKFb
+ jQIACgAbxRC61SgAoACwUQyhW40CAAoAG8UQutUoAKAAsFEMoVuNAgAKABvFELrVKACgALBRDKFbjQIA
+ CgAbxRC61SgAoACwUQyhW40CAAoAG8UQutUoAKAAsFEMoVuNAgAKABvFELrVKACgALBRDKFbjQIACgAb
+ xRC61SgAoACwUQyhW40CAAoAG8UQutUoAKAAsFEMoVuNAgAKABvFELrVKACgALBRDKFbjQIACgAbxRC6
+ 1SgAoACwUQyhW40CAAoAG8UQutUoAKAAsFEMoVuNAgAKABvFELrVKACgALBRDKFbjQIACgAbxRC61SgA
+ oACwUQyhW40CAAoAG8UQutUoAKAAsFEMoVuNAgAKABvFELrVKACgALBRDKFbjQIACgAbxRC61SgAoACw
+ UQyhW40CAAoAG8UQutUoAKAAsFEMoVuNAgAKABvFELrVKACgALBRDKFbjQIACgAbxRC61SgAoACwUQyh
+ W40CAAoAG8UQutUoAKAAsFEMoVuNAgAKABvFELrVKACgALBRDKFbjQIACgAbxRC61SgAoACwUQyhW40C
+ AAoAG8UQutUoAKAAsFEMoVuNAgAKABvFELrVKACgALBRDKFbjQIACgAbxRC61SgAoACwUQyhW40CAAoA
+ G8UQutUoAKAAsFEMoVuNAgAKABvFELrVKACgALBRDKFbjQIACgAbxRC61SgAoACwUQyhW40CAAoAG8UQ
+ utUoAKAAsFEMoVuNAgAKABvFELrVKACgALBRDKFbjQIACgAbxRC61SgAoACwUQyhW40CAAoAG8UQutUo
+ AKAAsFEMoVuNAgAKABvFELrVKACgALBRDKFbjQIACgAbxRC61SgAoACwUQyhW40CAAoAG8UQutUoAKAA
+ sFEMoVuNAgAKABvFELrVKACgALBRDKFbjQIACgAbxRC61SgAoACwUQyhW40CAAoAG8UQutUoAKAAsFEM
+ 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
+ FABQANgkhtChRgEABYBNYggdahQAUADYJIbQoUYBAAWATWIIHWoUAFAA2CSG0KFGAQAFgE1iCB1qFABQ
+ ANgkhtChRgEABYBNYggdahQAUADYJIbQoUYBAAWATWIIHWoUAFAA2CSG0KFGAQAFgE1iCB1qFABQANgk
+ htChRgEABYBNYggdahQAUADYJIbQoUYBAAWATWIIHWoUAFAA2CSG0KFGAQAFgE1iCB1qFABQANgkhtCh
+ RgEABYBNYggdahQAUADYJIbQoUYBAAWATWIIHWoUAFAA2CSG0KFGAQAFgE1iCB1qFABQANgkhtChRgEA
+ BYBNYggdahQAUADYJIbQoUYBAAWATWIIHWoUAFAA2CSG0KFGAQAFgE1iCB1qFABQANgkhtChRgEABYBN
+ YggdahQAUADYJIbQoUYBAAWATWIIHWoUAFAA2CSG0KFGAQAFgE1iCB1qFABQANgkhtChRgEABYBNYggd
+ ahQAUADYJIbQoUYBAAWATWIIHWoUAFAA2CSG0KFGAQAFgE1iCB1qFABQANgkhtChRgEABYBNYggdahQA
+ UADYJIbQoUYBAAWATWIIHWoUAFAA2CSG0KFGAQAFgE1iCB1qFABQANgkhtChRgEABYBNYggdahQAUADY
+ JIbQoUYBAAWATWIIHWoUAFAA2CSG0KFGAQAFgE1iCB1qFABQANgkhtChRgEABYBNYggdahQAUADYJIbQ
+ oUYBAAWATWIIHWoUAFAA2CSG0KFGAQAFgE1iCB1qFABQANgkhtChRgEABYBNYggdahQAUADYJIbQoUYB
+ AAWATWIIHWoUAFAA2CSG0KFGAQAFgE1iCB1qFABQANgkhtChRgEABYBNYggdahQAUADYJIbQoUYBAAWA
+ TWIIHWoUAFAA2CSG0KFGAQAFgE1iCB1qFABQANgkhtChRgEABYBNYggdahQAUADYJIbQoUYBAAWATWII
+ HWoUAFAA2CSG0KFGAQAFgE1iCB1qFABQANgkhtChRgEABYBNYggdahQAUADYJIbQoUYBAAWATWIIHWoU
+ AFAA2CSG0KFGAQAFgE1iCB1qFABQANgkhtChRgEABYBNYggdahQAUADYJIbQoUYBAAWATWIIHWoUAFAA
+ 2CSG0KFGAQAFgE1iCB1qFABQANgkhtChRgEABYBNYggdahQAUADYJIbQoUYBAAWATWIIHWoUAFAA2CSG
+ 0KFGAQAFgE1iCB1qFABQANgkhtChRgEABYBNYggdahQAUADYJIbQoUYBAAWATWIIHWoUAFAA2CSG0KFG
+ AQAFgE1iCB1qFABQANgkhtChRgEABYBNYggdahQAUADYJIbQoUYBAAWATWIIHWoUAFAA2CSG0KFGAQAF
+ gE1iCB1qFABQANgkhtChRgEABYBNYggdahQAUADYJIbQoUYBAAWATWIIHWoUAFAA2CSG0KFGAQAFgE1i
+ CB1qFABQANgkhtChRgEABYBNYggdahQAUADYJIbQoUYBAAWATWIIHWoUAFAA2CSG0KFGAQAFgE1iCB1q
+ FABQANgkhtChRgEABYBNYggdahQAUADYJIbQoUYBAAWATWIIHWoUAFAA2CSG0KFGAQAFgE1iCB1qFABQ
+ ANgkhtChRgEABYBNYggdahQAUADYJIbQoUYBAAWATWIIHWoUAFAA2CSG0KFGAQAFgE1iCB1qFABQANgk
+ htChRgEABYBNYggdahQAUADYJIbQoUYBAAWATWIIHWoUAFAA2CSG0KFGAQAFgE1iCB1qFABQANgkhtCh
+ RgEABYBNYggdahQAUADYJIbQoUYBAAWATWIIHWoUAFAA2CSG0KFGAQAFgE1iCB1qFABQANgkhtChRgEA
+ BYBNYggdahQAUADYJIbQoUYBAAWATWIIHWoUAFAA2CSG0KFGAQAFgE1iCB1qFABQANgkhtChRgEABYBN
+ YggdahQAUADYJIbQoUYBAAWATWIIHWoUAFAA2CSG0KFGAQAFgE1iCB1qFABQANgkhtChRgEABYBNYggd
+ ahQAUADYJIbQoUYBAAWATWIIHWoUAFAA2CSG0KFGAQAFgE1iCB1qFABQANgkhtChRgEABYBNYggdahQA
+ UADYJIbQoUYBAAWATWIIHWoUAFAA2CSG0KFGAQAFgE1iCB1qFABQANgkhtChRgEABYBNYggdahQAUADY
+ JIbQoUYBAAWATWIIHWoUAFAA2CSG0KFGAQAFgE1iCB1qFABQANgkhtChRgEABYBNYggdahQAUADYJIbQ
+ oUYBAAWATWIIHWoUAFAA2CSG0KFGAQAFgE1iCB1qFABQANgkhtChRgEABYBNYggdahQAUADYJIbQoUYB
+ AAWATWIIHWoUAFAA2CSG0KFGAQAFgE1iCB1qFABQANgkhtChRgEABYBNYggdahQAUADYJIbQoUYBAAWA
+ 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
+ SUVORK5CYII=
+
+
+
\ No newline at end of file
diff --git a/ProjectAirPlane/ProjectAirPlane/FormPlaneCollection.Designer.cs b/ProjectAirPlane/ProjectAirPlane/FormPlaneCollection.Designer.cs
new file mode 100644
index 0000000..b13da08
--- /dev/null
+++ b/ProjectAirPlane/ProjectAirPlane/FormPlaneCollection.Designer.cs
@@ -0,0 +1,303 @@
+namespace ProjectAirPlane
+{
+ partial class FormPlaneCollection
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ groupBoxTools = new GroupBox();
+ panelCompanyTools = new Panel();
+ buttonAddPlane = new Button();
+ buttonAddAirPlane = new Button();
+ maskedTextBox = new MaskedTextBox();
+ buttonRefresh = new Button();
+ buttonRemovePlane = new Button();
+ buttonGoToCheck = new Button();
+ buttonCreateCompany = new Button();
+ panelStorage = new Panel();
+ buttonCollectionDel = new Button();
+ listBoxCollection = new ListBox();
+ buttonCollectionAdd = new Button();
+ radioButtonList = new RadioButton();
+ radioButtonMassive = new RadioButton();
+ textBoxCollectionName = new TextBox();
+ labelCollectionName = new Label();
+ comboBoxSelectorCompany = new ComboBox();
+ pictureBox = new PictureBox();
+ groupBoxTools.SuspendLayout();
+ panelCompanyTools.SuspendLayout();
+ panelStorage.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)pictureBox).BeginInit();
+ SuspendLayout();
+ //
+ // groupBoxTools
+ //
+ groupBoxTools.Controls.Add(panelCompanyTools);
+ groupBoxTools.Controls.Add(buttonCreateCompany);
+ groupBoxTools.Controls.Add(panelStorage);
+ groupBoxTools.Controls.Add(comboBoxSelectorCompany);
+ groupBoxTools.Dock = DockStyle.Right;
+ groupBoxTools.Location = new Point(686, 0);
+ groupBoxTools.Name = "groupBoxTools";
+ groupBoxTools.Size = new Size(195, 558);
+ groupBoxTools.TabIndex = 0;
+ groupBoxTools.TabStop = false;
+ groupBoxTools.Text = "Инструменты";
+ //
+ // panelCompanyTools
+ //
+ panelCompanyTools.Controls.Add(buttonAddPlane);
+ panelCompanyTools.Controls.Add(buttonAddAirPlane);
+ panelCompanyTools.Controls.Add(maskedTextBox);
+ panelCompanyTools.Controls.Add(buttonRefresh);
+ panelCompanyTools.Controls.Add(buttonRemovePlane);
+ panelCompanyTools.Controls.Add(buttonGoToCheck);
+ panelCompanyTools.Dock = DockStyle.Bottom;
+ panelCompanyTools.Enabled = false;
+ panelCompanyTools.Location = new Point(3, 340);
+ panelCompanyTools.Name = "panelCompanyTools";
+ panelCompanyTools.Size = new Size(189, 215);
+ panelCompanyTools.TabIndex = 8;
+ //
+ // buttonAddPlane
+ //
+ buttonAddPlane.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
+ buttonAddPlane.Location = new Point(3, 13);
+ buttonAddPlane.Name = "buttonAddPlane";
+ buttonAddPlane.Size = new Size(166, 28);
+ buttonAddPlane.TabIndex = 1;
+ buttonAddPlane.Text = "Добавление самолёта";
+ buttonAddPlane.UseVisualStyleBackColor = true;
+ buttonAddPlane.Click += ButtonAddPlane_Click;
+ //
+ // buttonAddAirPlane
+ //
+ buttonAddAirPlane.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
+ buttonAddAirPlane.Location = new Point(3, 47);
+ buttonAddAirPlane.Name = "buttonAddAirPlane";
+ buttonAddAirPlane.Size = new Size(166, 38);
+ buttonAddAirPlane.TabIndex = 2;
+ buttonAddAirPlane.Text = "Добавление самолёта с радаром";
+ buttonAddAirPlane.UseVisualStyleBackColor = true;
+ buttonAddAirPlane.Click += ButtonAddAirPlane_Click;
+ //
+ // maskedTextBox
+ //
+ maskedTextBox.Location = new Point(3, 91);
+ maskedTextBox.Mask = "00";
+ maskedTextBox.Name = "maskedTextBox";
+ maskedTextBox.Size = new Size(166, 23);
+ maskedTextBox.TabIndex = 3;
+ maskedTextBox.ValidatingType = typeof(int);
+ maskedTextBox.MaskInputRejected += MaskedTextBox_MaskInputRejected;
+ //
+ // buttonRefresh
+ //
+ buttonRefresh.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
+ buttonRefresh.Location = new Point(4, 181);
+ buttonRefresh.Name = "buttonRefresh";
+ buttonRefresh.Size = new Size(166, 25);
+ buttonRefresh.TabIndex = 6;
+ buttonRefresh.Text = "Обновить";
+ buttonRefresh.UseVisualStyleBackColor = true;
+ buttonRefresh.Click += ButtonRefresh_Click;
+ //
+ // buttonRemovePlane
+ //
+ buttonRemovePlane.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
+ buttonRemovePlane.Location = new Point(3, 120);
+ buttonRemovePlane.Name = "buttonRemovePlane";
+ buttonRemovePlane.Size = new Size(166, 24);
+ buttonRemovePlane.TabIndex = 4;
+ buttonRemovePlane.Text = "Удалить самолёт";
+ buttonRemovePlane.UseVisualStyleBackColor = true;
+ buttonRemovePlane.Click += ButtonRemovePlane_Click;
+ //
+ // buttonGoToCheck
+ //
+ buttonGoToCheck.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
+ buttonGoToCheck.Location = new Point(4, 150);
+ buttonGoToCheck.Name = "buttonGoToCheck";
+ buttonGoToCheck.Size = new Size(166, 25);
+ buttonGoToCheck.TabIndex = 5;
+ buttonGoToCheck.Text = "Передать на тесты";
+ buttonGoToCheck.UseVisualStyleBackColor = true;
+ buttonGoToCheck.Click += ButtonGoToCheck_Click;
+ //
+ // buttonCreateCompany
+ //
+ buttonCreateCompany.Location = new Point(6, 314);
+ buttonCreateCompany.Name = "buttonCreateCompany";
+ buttonCreateCompany.Size = new Size(177, 23);
+ buttonCreateCompany.TabIndex = 7;
+ buttonCreateCompany.Text = "Создать компанию";
+ buttonCreateCompany.UseVisualStyleBackColor = true;
+ buttonCreateCompany.Click += ButtonCreateCompany_Click;
+ //
+ // panelStorage
+ //
+ panelStorage.Controls.Add(buttonCollectionDel);
+ panelStorage.Controls.Add(listBoxCollection);
+ panelStorage.Controls.Add(buttonCollectionAdd);
+ panelStorage.Controls.Add(radioButtonList);
+ panelStorage.Controls.Add(radioButtonMassive);
+ panelStorage.Controls.Add(textBoxCollectionName);
+ panelStorage.Controls.Add(labelCollectionName);
+ panelStorage.Dock = DockStyle.Top;
+ panelStorage.Location = new Point(3, 19);
+ panelStorage.Name = "panelStorage";
+ panelStorage.Size = new Size(189, 260);
+ panelStorage.TabIndex = 7;
+ //
+ // buttonCollectionDel
+ //
+ buttonCollectionDel.Location = new Point(7, 226);
+ buttonCollectionDel.Name = "buttonCollectionDel";
+ buttonCollectionDel.Size = new Size(173, 23);
+ buttonCollectionDel.TabIndex = 6;
+ buttonCollectionDel.Text = "Удалить коллекцию";
+ buttonCollectionDel.UseVisualStyleBackColor = true;
+ buttonCollectionDel.Click += ButtonCollectionDel_Click;
+ //
+ // listBoxCollection
+ //
+ listBoxCollection.FormattingEnabled = true;
+ listBoxCollection.ItemHeight = 15;
+ listBoxCollection.Location = new Point(7, 113);
+ listBoxCollection.Name = "listBoxCollection";
+ listBoxCollection.Size = new Size(173, 109);
+ listBoxCollection.TabIndex = 5;
+ //
+ // buttonCollectionAdd
+ //
+ buttonCollectionAdd.Location = new Point(7, 81);
+ buttonCollectionAdd.Name = "buttonCollectionAdd";
+ buttonCollectionAdd.Size = new Size(174, 25);
+ buttonCollectionAdd.TabIndex = 4;
+ buttonCollectionAdd.Text = "Добавить коллекцию";
+ buttonCollectionAdd.UseVisualStyleBackColor = true;
+ buttonCollectionAdd.Click += ButtonCollectionAdd_Click;
+ //
+ // radioButtonList
+ //
+ radioButtonList.AutoSize = true;
+ radioButtonList.Location = new Point(114, 56);
+ radioButtonList.Name = "radioButtonList";
+ radioButtonList.Size = new Size(66, 19);
+ radioButtonList.TabIndex = 3;
+ radioButtonList.TabStop = true;
+ radioButtonList.Text = "Список";
+ radioButtonList.UseVisualStyleBackColor = true;
+ //
+ // radioButtonMassive
+ //
+ radioButtonMassive.AutoSize = true;
+ radioButtonMassive.Location = new Point(6, 56);
+ radioButtonMassive.Name = "radioButtonMassive";
+ radioButtonMassive.Size = new Size(67, 19);
+ radioButtonMassive.TabIndex = 2;
+ radioButtonMassive.TabStop = true;
+ radioButtonMassive.Text = "Массив";
+ radioButtonMassive.UseVisualStyleBackColor = true;
+ //
+ // textBoxCollectionName
+ //
+ textBoxCollectionName.Location = new Point(3, 27);
+ textBoxCollectionName.Name = "textBoxCollectionName";
+ textBoxCollectionName.Size = new Size(181, 23);
+ textBoxCollectionName.TabIndex = 1;
+ //
+ // labelCollectionName
+ //
+ labelCollectionName.AutoSize = true;
+ labelCollectionName.Location = new Point(40, 9);
+ labelCollectionName.Name = "labelCollectionName";
+ labelCollectionName.Size = new Size(122, 15);
+ labelCollectionName.TabIndex = 0;
+ labelCollectionName.Text = "Название коллекции";
+ //
+ // comboBoxSelectorCompany
+ //
+ comboBoxSelectorCompany.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
+ comboBoxSelectorCompany.DropDownStyle = ComboBoxStyle.DropDownList;
+ comboBoxSelectorCompany.FormattingEnabled = true;
+ comboBoxSelectorCompany.Items.AddRange(new object[] { "Хранилище" });
+ comboBoxSelectorCompany.Location = new Point(6, 285);
+ comboBoxSelectorCompany.Name = "comboBoxSelectorCompany";
+ comboBoxSelectorCompany.Size = new Size(178, 23);
+ comboBoxSelectorCompany.TabIndex = 0;
+ comboBoxSelectorCompany.SelectedIndexChanged += ComboBoxSelectorCompany_SelectedIndexChanged;
+ //
+ // pictureBox
+ //
+ pictureBox.Dock = DockStyle.Fill;
+ pictureBox.Location = new Point(0, 0);
+ pictureBox.Name = "pictureBox";
+ pictureBox.Size = new Size(686, 558);
+ pictureBox.TabIndex = 1;
+ pictureBox.TabStop = false;
+ //
+ // FormPlaneCollection
+ //
+ AutoScaleDimensions = new SizeF(7F, 15F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(881, 558);
+ Controls.Add(pictureBox);
+ Controls.Add(groupBoxTools);
+ Name = "FormPlaneCollection";
+ Text = "Коллекция самолётов";
+ groupBoxTools.ResumeLayout(false);
+ panelCompanyTools.ResumeLayout(false);
+ panelCompanyTools.PerformLayout();
+ panelStorage.ResumeLayout(false);
+ panelStorage.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)pictureBox).EndInit();
+ ResumeLayout(false);
+ }
+
+ #endregion
+
+ private GroupBox groupBoxTools;
+ private ComboBox comboBoxSelectorCompany;
+ private Button buttonAddPlane;
+ private Button buttonAddAirPlane;
+ private PictureBox pictureBox;
+ private Button buttonRemovePlane;
+ private MaskedTextBox maskedTextBox;
+ private Button buttonGoToCheck;
+ private Button buttonRefresh;
+ private Panel panelStorage;
+ private Label labelCollectionName;
+ private TextBox textBoxCollectionName;
+ private RadioButton radioButtonMassive;
+ private RadioButton radioButtonList;
+ private Button buttonCollectionAdd;
+ private ListBox listBoxCollection;
+ private Button buttonCollectionDel;
+ private Button buttonCreateCompany;
+ private Panel panelCompanyTools;
+ }
+}
\ No newline at end of file
diff --git a/ProjectAirPlane/ProjectAirPlane/FormPlaneCollection.cs b/ProjectAirPlane/ProjectAirPlane/FormPlaneCollection.cs
new file mode 100644
index 0000000..f82c901
--- /dev/null
+++ b/ProjectAirPlane/ProjectAirPlane/FormPlaneCollection.cs
@@ -0,0 +1,276 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using ProjectAirPlane.CollectionGenericObjects;
+using ProjectAirPlane.Drawnings;
+
+namespace ProjectAirPlane;
+
+///
+/// Форма работы с компанией и ее коллекцией
+///
+public partial class FormPlaneCollection : Form
+{
+ ///
+ /// Хранилише коллекций
+ ///
+ private readonly StorageCollection _storageCollection;
+
+ ///
+ /// Компания
+ ///
+ private AbstractCompany? _company = null;
+
+ ///
+ /// Конструктор
+ ///
+ public FormPlaneCollection()
+ {
+ InitializeComponent();
+ _storageCollection = new();
+ }
+
+ ///
+ /// Выбор компании
+ ///
+ ///
+ ///
+ private void ComboBoxSelectorCompany_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ panelCompanyTools.Enabled = false;
+ }
+
+ ///
+ /// Создание объекта класса-перемещения
+ ///
+ /// Тип создаваемого объекта
+ private void CreateObject(string type)
+ {
+ if (_company == null)
+ {
+ return;
+ }
+
+ Random random = new();
+ DrawningPlane drawningPlane;
+ switch (type)
+ {
+ case nameof(DrawningPlane):
+ drawningPlane = new DrawningPlane(random.Next(100, 300), random.Next(1000, 3000), GetColor(random));
+ break;
+ case nameof(DrawningAirPlane):
+ // TODO вызов диалогового окна для выбора цвета
+ drawningPlane = new DrawningAirPlane(random.Next(100, 300), random.Next(1000, 3000),
+ GetColor(random), GetColor(random),
+ Convert.ToBoolean(random.Next(0, 2)), Convert.ToBoolean(random.Next(0, 2)), Convert.ToBoolean(random.Next(0, 2)));
+ break;
+ default:
+ return;
+ }
+
+ if (_company + drawningPlane != -1)
+ {
+ MessageBox.Show("Объект добавлен");
+ pictureBox.Image = _company.Show();
+ }
+ else
+ {
+ MessageBox.Show("Не удалось добавить объект");
+ }
+ }
+
+ ///
+ /// Получение цвета
+ ///
+ /// Генератор случайных чисел
+ ///
+ private static Color GetColor(Random random)
+ {
+ Color color = Color.FromArgb(random.Next(0, 256), random.Next(0, 256), random.Next(0, 256));
+ ColorDialog dialog = new();
+ if (dialog.ShowDialog() == DialogResult.OK)
+ {
+ color = dialog.Color;
+ }
+
+ return color;
+ }
+ private void ButtonAddPlane_Click(object sender, EventArgs e) => CreateObject(nameof(DrawningPlane));
+
+
+
+
+ private void ButtonAddAirPlane_Click(object sender, EventArgs e) => CreateObject(nameof(DrawningAirPlane));
+
+
+ private void MaskedTextBox_MaskInputRejected(object sender, MaskInputRejectedEventArgs e)
+ {
+
+ }
+
+ private void ButtonRemovePlane_Click(object sender, EventArgs e)
+ {
+ if (string.IsNullOrEmpty(maskedTextBox.Text) || _company == null)
+ {
+ return;
+ }
+
+ if (MessageBox.Show("Удалить объект?", "Удаление", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes)
+ {
+ return;
+ }
+
+ int pos = Convert.ToInt32(maskedTextBox.Text);
+ if (_company - pos != null)
+ {
+ MessageBox.Show("Объект удален");
+ pictureBox.Image = _company.Show();
+ }
+ else
+ {
+ MessageBox.Show("Не удалось удалить объект");
+ }
+ }
+
+ private void ButtonGoToCheck_Click(object sender, EventArgs e)
+ {
+ if (_company == null)
+ {
+ return;
+ }
+
+ DrawningPlane? plane = null;
+ int counter = 100;
+ while (plane == null)
+ {
+ plane = _company.GetRandomObject();
+ counter--;
+ if (counter <= 0)
+ {
+ break;
+ }
+ }
+
+ if (plane == null)
+ {
+ return;
+ }
+
+ FormAirPlane form = new()
+ {
+ SetPlane = plane
+ };
+ form.ShowDialog();
+ }
+
+ private void ButtonRefresh_Click(object sender, EventArgs e)
+ {
+ if (_company == null)
+ {
+ return;
+ }
+
+ pictureBox.Image = _company.Show();
+ }
+
+
+ ///
+ /// Добавление коллекции
+ ///
+ ///
+ ///
+ private void ButtonCollectionAdd_Click(object sender, EventArgs e)
+ {
+ if (string.IsNullOrEmpty(textBoxCollectionName.Text) || (!radioButtonList.Checked && !radioButtonMassive.Checked))
+ {
+ MessageBox.Show("Не все данные заполнены", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
+ }
+
+ CollectionType collectionType = CollectionType.None;
+ if (radioButtonMassive.Checked)
+ {
+ collectionType = CollectionType.Massive;
+ }
+ else if (radioButtonList.Checked)
+ {
+ collectionType = CollectionType.List;
+ }
+
+ _storageCollection.AddCollection(textBoxCollectionName.Text, collectionType);
+ RerfreshListBoxItems();
+ }
+
+ ///
+ /// Обновление списка в listBoxCollection
+ ///
+ private void RerfreshListBoxItems()
+ {
+ listBoxCollection.Items.Clear();
+ for (int i = 0; i < _storageCollection.Keys?.Count; ++i)
+ {
+ string? colName = _storageCollection.Keys?[i];
+ if (!string.IsNullOrEmpty(colName))
+ {
+ listBoxCollection.Items.Add(colName);
+ }
+ }
+
+ }
+ ///
+ /// Удаление коллекции
+ ///
+ ///
+ ///
+ private void ButtonCollectionDel_Click(object sender, EventArgs e)
+ {
+ if (listBoxCollection.SelectedIndex < 0 || listBoxCollection.SelectedItem == null)
+ {
+ MessageBox.Show("Коллекция не выбрана");
+ return;
+ }
+ if (MessageBox.Show("Удалить коллекцию?", "Удаление", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
+ {
+ return;
+ }
+ _storageCollection.DelCollection(listBoxCollection.SelectedItem.ToString());
+ RerfreshListBoxItems();
+ }
+ ///
+ /// Создание компании
+ ///
+ ///
+ ///
+ private void ButtonCreateCompany_Click(object sender, EventArgs e)
+ {
+ if (listBoxCollection.SelectedIndex < 0 || listBoxCollection.SelectedItem == null)
+ {
+ MessageBox.Show("Коллекция не выбрана");
+ return;
+ }
+
+ ICollectionGenericObjects? collection = _storageCollection[listBoxCollection.SelectedItem.ToString() ?? string.Empty];
+ if (collection == null)
+ {
+ MessageBox.Show("Коллекция не проинициализирована");
+ return;
+ }
+
+ switch (comboBoxSelectorCompany.Text)
+ {
+ case "Хранилище":
+ _company = new PlaneSharingService(pictureBox.Width, pictureBox.Height, collection);
+ break;
+ }
+
+ panelCompanyTools.Enabled = true;
+ RerfreshListBoxItems();
+ }
+}
+
diff --git a/ProjectAirPlane/ProjectAirPlane/FormPlaneCollection.resx b/ProjectAirPlane/ProjectAirPlane/FormPlaneCollection.resx
new file mode 100644
index 0000000..af32865
--- /dev/null
+++ b/ProjectAirPlane/ProjectAirPlane/FormPlaneCollection.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/ProjectAirPlane/ProjectAirPlane/MovementStrategy/AbstractStrategy.cs b/ProjectAirPlane/ProjectAirPlane/MovementStrategy/AbstractStrategy.cs
new file mode 100644
index 0000000..a81c6fe
--- /dev/null
+++ b/ProjectAirPlane/ProjectAirPlane/MovementStrategy/AbstractStrategy.cs
@@ -0,0 +1,139 @@
+namespace ProjectAirPlane.MovementStrategy;
+
+///
+/// Класс-стратегия перемещения объекта
+///
+public abstract class AbstractStrategy
+{
+ ///
+ /// Перемещаемый объект
+ ///
+ private IMoveableObject? _moveableObject;
+
+ ///
+ /// Статус перемещения
+ ///
+ private StrategyStatus _state = StrategyStatus.NotInit;
+
+ ///
+ /// Ширина поля
+ ///
+ protected int FieldWidth { get; private set; }
+
+ ///
+ /// Высота поля
+ ///
+ protected int FieldHeight { get; private set; }
+
+ ///
+ /// Статус перемещения
+ ///
+ public StrategyStatus GetStatus() { return _state; }
+
+ ///
+ /// Установка данных
+ ///
+ /// Перемещаемый объект
+ /// Ширина поля
+ /// Высота поля
+ public void SetData(IMoveableObject moveableObject, int width, int height)
+ {
+ if (moveableObject == null)
+ {
+ _state = StrategyStatus.NotInit;
+ return;
+ }
+
+ _state = StrategyStatus.InProgress;
+ _moveableObject = moveableObject;
+ FieldWidth = width;
+ FieldHeight = height;
+ }
+
+ ///
+ /// Шаг перемещения
+ ///
+ public void MakeStep()
+ {
+ if (_state != StrategyStatus.InProgress)
+ {
+ return;
+ }
+
+ if (IsTargetDestinaion())
+ {
+ _state = StrategyStatus.Finish;
+ return;
+ }
+
+ MoveToTarget();
+ }
+
+ ///
+ /// Перемещение влево
+ ///
+ /// Результат перемещения (true - удалось переместиться, false - неудача)
+ protected bool MoveLeft() => MoveTo(MovementDirection.Left);
+
+ ///
+ /// Перемещение вправо
+ ///
+ /// Результат перемещения (true - удалось переместиться, false - неудача)
+ protected bool MoveRight() => MoveTo(MovementDirection.Right);
+
+ ///
+ /// Перемещение вверх
+ ///
+ /// Результат перемещения (true - удалось переместиться, false - неудача)
+ protected bool MoveUp() => MoveTo(MovementDirection.Up);
+
+ ///
+ /// Перемещение вниз
+ ///
+ /// Результат перемещения (true - удалось переместиться, false - неудача)
+ protected bool MoveDown() => MoveTo(MovementDirection.Down);
+
+ ///
+ /// Параметры объекта
+ ///
+ protected ObjectParameters? GetObjectParameters => _moveableObject?.GetObjectPosition;
+
+ ///
+ /// Шаг объекта
+ ///
+ ///
+ protected int? GetStep()
+ {
+ if (_state != StrategyStatus.InProgress)
+ {
+ return null;
+ }
+ return _moveableObject?.GetStep;
+ }
+
+ ///
+ /// Перемещение к цели
+ ///
+ protected abstract void MoveToTarget();
+
+ ///
+ /// Достигнута ли цель
+ ///
+ ///
+ protected abstract bool IsTargetDestinaion();
+
+ ///
+ /// Попытка перемещения в требуемом направлении
+ ///
+ /// Направление
+ /// Результат попытки (true - удалось переместиться, false - неудача)
+ private bool MoveTo(MovementDirection movementDirection)
+ {
+ if (_state != StrategyStatus.InProgress)
+ {
+ return false;
+ }
+
+ return _moveableObject?.TryMoveObject(movementDirection) ?? false;
+ }
+}
\ No newline at end of file
diff --git a/ProjectAirPlane/ProjectAirPlane/MovementStrategy/IMoveableObject.cs b/ProjectAirPlane/ProjectAirPlane/MovementStrategy/IMoveableObject.cs
new file mode 100644
index 0000000..51bec7c
--- /dev/null
+++ b/ProjectAirPlane/ProjectAirPlane/MovementStrategy/IMoveableObject.cs
@@ -0,0 +1,26 @@
+namespace ProjectAirPlane.MovementStrategy;
+
+///
+/// Интерфейс для работы с перемещаемым объектом
+///
+public interface IMoveableObject
+{
+ ///
+ /// Получение координаты объекта
+ ///
+ ObjectParameters? GetObjectPosition { get; }
+
+ ///
+ /// Шаг объекта
+ ///
+ int GetStep { get; }
+
+ ///
+ /// Попытка переместить объект в указанном направлении
+ ///
+ /// Направление
+ /// true - объект перемещен, false - перемещение невозможно
+ bool TryMoveObject(MovementDirection direction);
+
+ protected void Move();
+}
\ No newline at end of file
diff --git a/ProjectAirPlane/ProjectAirPlane/MovementStrategy/MoveToBorder.cs b/ProjectAirPlane/ProjectAirPlane/MovementStrategy/MoveToBorder.cs
new file mode 100644
index 0000000..039e6ed
--- /dev/null
+++ b/ProjectAirPlane/ProjectAirPlane/MovementStrategy/MoveToBorder.cs
@@ -0,0 +1,31 @@
+namespace ProjectAirPlane.MovementStrategy;
+
+public class MoveToBorder : AbstractStrategy
+{
+ protected override bool IsTargetDestinaion()
+ {
+ ObjectParameters? objParams = GetObjectParameters;
+ if (objParams == null) return false;
+
+ return objParams.RightBorder + GetStep() >= FieldWidth
+ && objParams.DownBorder + GetStep() >= FieldHeight;
+ }
+
+ protected override void MoveToTarget()
+ {
+ ObjectParameters? objParams = GetObjectParameters;
+ if (objParams == null) return;
+
+ int diffX = objParams.LeftBorder - FieldWidth;
+ if (Math.Abs(diffX) > GetStep())
+ {
+ MoveRight();
+ }
+
+ int diffY = objParams.DownBorder - FieldHeight;
+ if (Math.Abs(diffY) > GetStep())
+ {
+ MoveDown();
+ }
+ }
+}
diff --git a/ProjectAirPlane/ProjectAirPlane/MovementStrategy/MoveToCenter.cs b/ProjectAirPlane/ProjectAirPlane/MovementStrategy/MoveToCenter.cs
new file mode 100644
index 0000000..f2dfc0d
--- /dev/null
+++ b/ProjectAirPlane/ProjectAirPlane/MovementStrategy/MoveToCenter.cs
@@ -0,0 +1,52 @@
+
+namespace ProjectAirPlane.MovementStrategy;
+
+///
+/// Стратегия перемещения объекта в центр экрана
+///
+public class MoveToCenter : AbstractStrategy
+{
+ protected override bool IsTargetDestinaion()
+ {
+ ObjectParameters? objParams = GetObjectParameters;
+ if (objParams == null)
+ {
+ return false;
+ }
+ return objParams.ObjectMiddleHorizontal - GetStep() <= FieldWidth / 2 && objParams.ObjectMiddleHorizontal + GetStep() >= FieldWidth / 2 &&
+ objParams.ObjectMiddleVertical - GetStep() <= FieldHeight / 2 && objParams.ObjectMiddleVertical + GetStep() >= FieldHeight / 2;
+ }
+ protected override void MoveToTarget()
+ {
+ ObjectParameters? objParams = GetObjectParameters;
+ if (objParams == null)
+ {
+ return;
+ }
+ int diffX = objParams.ObjectMiddleHorizontal - FieldWidth / 2;
+ if (Math.Abs(diffX) > GetStep())
+ {
+ if (diffX > 0)
+ {
+ MoveLeft();
+ }
+ else
+ {
+ MoveRight();
+ }
+ }
+ int diffY = objParams.ObjectMiddleVertical - FieldHeight / 2;
+ if (Math.Abs(diffY) > GetStep())
+ {
+ if (diffY > 0)
+ {
+ MoveUp();
+ }
+ else
+ {
+ MoveDown();
+ }
+ }
+ }
+}
+
diff --git a/ProjectAirPlane/ProjectAirPlane/MovementStrategy/MoveablePlane.cs b/ProjectAirPlane/ProjectAirPlane/MovementStrategy/MoveablePlane.cs
new file mode 100644
index 0000000..343743b
--- /dev/null
+++ b/ProjectAirPlane/ProjectAirPlane/MovementStrategy/MoveablePlane.cs
@@ -0,0 +1,66 @@
+using ProjectAirPlane.Drawnings;
+
+namespace ProjectAirPlane.MovementStrategy;
+
+public class MoveablePlane : IMoveableObject
+{
+ ///
+ /// Поле-объект класса DrawningPlane или его наследника
+ ///
+ private readonly DrawningPlane? _plane = null;
+
+ ///
+ /// Конструктор
+ ///
+ /// Объект класса DrawningPlane
+ public MoveablePlane(DrawningPlane plane)
+ {
+ _plane = plane;
+ }
+
+ public ObjectParameters? GetObjectPosition
+ {
+ get
+ {
+ if (_plane == null || _plane.EntityPlane == null || !_plane.GetPosX.HasValue || !_plane.GetPosY.HasValue)
+ {
+ return null;
+ }
+ return new ObjectParameters(_plane.GetPosX.Value, _plane.GetPosY.Value, _plane.GetWidth, _plane.GetHeight);
+ }
+ }
+
+ public int GetStep => (int)(_plane?.EntityPlane?.Step ?? 0);
+
+ public bool TryMoveObject(MovementDirection direction)
+ {
+ if (_plane == null || _plane.EntityPlane == null)
+ {
+ return false;
+ }
+
+ return _plane.MoveTransport(GetDirectionType(direction));
+ }
+
+ ///
+ /// Конвертация из MovementDirection в DirectionType
+ ///
+ /// MovementDirection
+ /// DirectionType
+ private static DirectionType GetDirectionType(MovementDirection direction)
+ {
+ return direction switch
+ {
+ MovementDirection.Left => DirectionType.Left,
+ MovementDirection.Right => DirectionType.Right,
+ MovementDirection.Up => DirectionType.Up,
+ MovementDirection.Down => DirectionType.Down,
+ _ => DirectionType.Unknow,
+ };
+ }
+
+ void IMoveableObject.Move()
+ {
+ throw new NotImplementedException();
+ }
+}
diff --git a/ProjectAirPlane/ProjectAirPlane/MovementStrategy/MovementDirection.cs b/ProjectAirPlane/ProjectAirPlane/MovementStrategy/MovementDirection.cs
new file mode 100644
index 0000000..df16368
--- /dev/null
+++ b/ProjectAirPlane/ProjectAirPlane/MovementStrategy/MovementDirection.cs
@@ -0,0 +1,28 @@
+namespace ProjectAirPlane.MovementStrategy;
+
+///
+/// Направление перемещения
+///
+public enum MovementDirection
+{
+
+ ///
+ /// Вверх
+ ///
+ Up = 1,
+
+ ///
+ /// Вниз
+ ///
+ Down = 2,
+
+ ///
+ /// Влево
+ ///
+ Left = 3,
+
+ ///
+ /// Вправо
+ ///
+ Right = 4
+}
diff --git a/ProjectAirPlane/ProjectAirPlane/MovementStrategy/ObjectParameters.cs b/ProjectAirPlane/ProjectAirPlane/MovementStrategy/ObjectParameters.cs
new file mode 100644
index 0000000..2f4872b
--- /dev/null
+++ b/ProjectAirPlane/ProjectAirPlane/MovementStrategy/ObjectParameters.cs
@@ -0,0 +1,71 @@
+namespace ProjectAirPlane.MovementStrategy;
+///
+/// Параметры-координаты объекта
+///
+public class ObjectParameters
+{
+ ///
+ /// Координата X
+ ///
+ private readonly int _x;
+
+ ///
+ /// Координата Y
+ ///
+ private readonly int _y;
+
+ ///
+ /// Ширина объекта
+ ///
+ private readonly int _width;
+
+ ///
+ /// Высота объекта
+ ///
+ private readonly int _height;
+
+ ///
+ /// Левая граница
+ ///
+ public int LeftBorder => _x;
+
+ ///
+ /// Верхняя граница
+ ///
+ public int TopBorder => _y;
+
+ ///
+ /// Правая граница
+ ///
+ public int RightBorder => _x + _width;
+
+ ///
+ /// Нижняя граница
+ ///
+ public int DownBorder => _y + _height;
+
+ ///
+ /// Середина объекта
+ ///
+ public int ObjectMiddleHorizontal => _x + _width / 2;
+
+ ///
+ /// Середина объекта
+ ///
+ public int ObjectMiddleVertical => _y + _height / 2;
+
+ ///
+ /// Конструктор
+ ///
+ /// Координата X
+ /// Координата Y
+ /// Ширина объекта
+ /// Высота объекта
+ public ObjectParameters(int x, int y, int width, int height)
+ {
+ _x = x;
+ _y = y;
+ _width = width;
+ _height = height;
+ }
+}
diff --git a/ProjectAirPlane/ProjectAirPlane/MovementStrategy/StrategyStatus.cs b/ProjectAirPlane/ProjectAirPlane/MovementStrategy/StrategyStatus.cs
new file mode 100644
index 0000000..ae076a8
--- /dev/null
+++ b/ProjectAirPlane/ProjectAirPlane/MovementStrategy/StrategyStatus.cs
@@ -0,0 +1,22 @@
+namespace ProjectAirPlane.MovementStrategy;
+
+///
+/// Статус выполнения операции перемещения
+///
+public enum StrategyStatus
+{
+ ///
+ /// Все готово к началу
+ ///
+ NotInit,
+
+ ///
+ /// Выполняется
+ ///
+ InProgress,
+
+ ///
+ /// Завершено
+ ///
+ Finish
+}
diff --git a/ProjectAirPlane/ProjectAirPlane/Program.cs b/ProjectAirPlane/ProjectAirPlane/Program.cs
index bc2d17a..831f9a4 100644
--- a/ProjectAirPlane/ProjectAirPlane/Program.cs
+++ b/ProjectAirPlane/ProjectAirPlane/Program.cs
@@ -11,7 +11,8 @@ namespace ProjectAirPlane
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();
- Application.Run(new Form1());
+ Application.Run(new FormPlaneCollection());
+
}
}
}
\ No newline at end of file
diff --git a/ProjectAirPlane/ProjectAirPlane/ProjectAirPlane.csproj b/ProjectAirPlane/ProjectAirPlane/ProjectAirPlane.csproj
index e1a0735..244387d 100644
--- a/ProjectAirPlane/ProjectAirPlane/ProjectAirPlane.csproj
+++ b/ProjectAirPlane/ProjectAirPlane/ProjectAirPlane.csproj
@@ -8,4 +8,19 @@
enable
+
+
+ True
+ True
+ Resources.resx
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
\ No newline at end of file
diff --git a/ProjectAirPlane/ProjectAirPlane/Properties/Resources.Designer.cs b/ProjectAirPlane/ProjectAirPlane/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..03696f3
--- /dev/null
+++ b/ProjectAirPlane/ProjectAirPlane/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// Этот код создан программой.
+// Исполняемая версия:4.0.30319.42000
+//
+// Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае
+// повторной генерации кода.
+//
+//------------------------------------------------------------------------------
+
+namespace ProjectAirPlane.Properties {
+ using System;
+
+
+ ///
+ /// Класс ресурса со строгой типизацией для поиска локализованных строк и т.д.
+ ///
+ // Этот класс создан автоматически классом StronglyTypedResourceBuilder
+ // с помощью такого средства, как ResGen или Visual Studio.
+ // Чтобы добавить или удалить член, измените файл .ResX и снова запустите ResGen
+ // с параметром /str или перестройте свой проект VS.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Возвращает кэшированный экземпляр ResourceManager, использованный этим классом.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ProjectAirPlane.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Перезаписывает свойство CurrentUICulture текущего потока для всех
+ /// обращений к ресурсу с помощью этого класса ресурса со строгой типизацией.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/ProjectAirPlane/ProjectAirPlane/Form1.resx b/ProjectAirPlane/ProjectAirPlane/Properties/Resources.resx
similarity index 100%
rename from ProjectAirPlane/ProjectAirPlane/Form1.resx
rename to ProjectAirPlane/ProjectAirPlane/Properties/Resources.resx
diff --git a/ProjectAirPlane/ProjectAirPlane/Resources/arrowDown.jpg b/ProjectAirPlane/ProjectAirPlane/Resources/arrowDown.jpg
new file mode 100644
index 0000000..f21002e
Binary files /dev/null and b/ProjectAirPlane/ProjectAirPlane/Resources/arrowDown.jpg differ
diff --git a/ProjectAirPlane/ProjectAirPlane/Resources/arrowLeft.jpg b/ProjectAirPlane/ProjectAirPlane/Resources/arrowLeft.jpg
new file mode 100644
index 0000000..61b8dae
Binary files /dev/null and b/ProjectAirPlane/ProjectAirPlane/Resources/arrowLeft.jpg differ
diff --git a/ProjectAirPlane/ProjectAirPlane/Resources/arrowRight.jpg b/ProjectAirPlane/ProjectAirPlane/Resources/arrowRight.jpg
new file mode 100644
index 0000000..b440197
Binary files /dev/null and b/ProjectAirPlane/ProjectAirPlane/Resources/arrowRight.jpg differ
diff --git a/ProjectAirPlane/ProjectAirPlane/Resources/arrowUp.jpg b/ProjectAirPlane/ProjectAirPlane/Resources/arrowUp.jpg
new file mode 100644
index 0000000..e630cea
Binary files /dev/null and b/ProjectAirPlane/ProjectAirPlane/Resources/arrowUp.jpg differ