From f604ea29fc949da5822375c1f6e3649b4d86dcc2 Mon Sep 17 00:00:00 2001 From: Nikita Potapov <47923521+nikita-potapov@users.noreply.github.com> Date: Fri, 4 Nov 2022 14:48:21 +0400 Subject: [PATCH] Generic classes --- Boats/Boats/MapWithSetBoatsGeneric.cs | 245 ++++++++++++++++++++++++++ Boats/Boats/SetBoatsGeneric.cs | 121 +++++++++++++ 2 files changed, 366 insertions(+) create mode 100644 Boats/Boats/MapWithSetBoatsGeneric.cs create mode 100644 Boats/Boats/SetBoatsGeneric.cs diff --git a/Boats/Boats/MapWithSetBoatsGeneric.cs b/Boats/Boats/MapWithSetBoatsGeneric.cs new file mode 100644 index 0000000..d52da8f --- /dev/null +++ b/Boats/Boats/MapWithSetBoatsGeneric.cs @@ -0,0 +1,245 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Boats +{ + /// + /// Карта с набром объектов + /// + /// + /// + internal class MapWithSetBoatsGeneric + where T : class, IDrawingObject + where U : AbstractMap + { + /// + /// Ширина окна отрисовки + /// + private readonly int _pictureWidth; + /// + /// Высота окна отрисовки + /// + private readonly int _pictureHeight; + /// + /// Размер занимаемого объектом места (ширина) + /// + private readonly int _placeSizeWidth = 130; + /// + /// Размер занимаемого объектом места (высота) + /// + private readonly int _placeSizeHeight = 80; + /// + /// Набор объектов + /// + private readonly SetBoatsGeneric _setBoats; + /// + /// Карта + /// + private readonly U _map; + /// + /// Массив точек установки лодок в гавани + /// + private Point[]? _placesPoints; + private readonly int _placesCount = 14; + /// + /// Конструктор + /// + /// + /// + /// + public MapWithSetBoatsGeneric(int picWidth, int picHeight, U map) + { + int width = picWidth / _placeSizeWidth; + int height = picHeight / _placeSizeHeight; + _setBoats = new SetBoatsGeneric(_placesCount); + _pictureWidth = picWidth; + _pictureHeight = picHeight; + _map = map; + _placesPoints = null; + } + /// + /// Перегрузка оператора сложения + /// + /// + /// + /// Возвращает позицию объекта в массиве или + /// -1, если установить объект не удплось + public static int operator +(MapWithSetBoatsGeneric map, T boat) + { + return map._setBoats.Insert(boat); + } + /// + /// Перегрузка оператора вычитания + /// + /// + /// + /// Возвращает удаляемый объект или + /// null, если удалить не удалось + public static T operator -(MapWithSetBoatsGeneric map, int position) + { + return map._setBoats.Remove(position); + } + /// + /// Вывод всего набора объектов + /// + /// Возвращает Bitmap с гаванью и лодками + public Bitmap ShowSet() + { + Bitmap bmp = new(_pictureWidth, _pictureHeight); + Graphics g = Graphics.FromImage(bmp); + DrawBackground(g); + DrawBoats(g); + return bmp; + } + /// + /// Просмотр объекта на карте + /// + /// Возвращает Bitmap с картой и объектом на ней + public Bitmap ShowOnMap() + { + Shaking(); + for (int i = 0; i < _setBoats.Count; i++) + { + var boat = _setBoats.Get(i); + if (boat != null) + { + return _map.CreateMap(_pictureWidth, _pictureHeight, boat); + } + } + return new(_pictureWidth, _pictureHeight); + } + /// + /// Перемещение объекта по карте + /// + /// + /// Возвращает Bitmap с картой и перемещенным объектом на ней + public Bitmap MoveObject(Direction direction) + { + if (_map != null) + { + return _map.MoveObject(direction); + } + return new(_pictureWidth, _pictureHeight); + } + /// + /// "Взбалтываем" набор, чтобы все элементы оказались в начале + /// + private void Shaking() + { + int j = _setBoats.Count - 1; + for (int i = 0; i < _setBoats.Count; i++) + { + if (_setBoats.Get(i) == null) + { + for (; j > i; j--) + { + var boat = _setBoats.Get(j); + if (boat != null) + { + _setBoats.Insert(boat, i); + _setBoats.Remove(j); + break; + } + } + if (j <= i) + { + return; + } + } + } + } + /// + /// Метод отрисовки фона + /// + /// + private void DrawBackground(Graphics g) + { + bool pointsInit = false; + // Если массив точек null, значит рисуем фон первый раз и + // инициализируем массив для его заполнения + if (_placesPoints == null) + { + _placesPoints = new Point[_placesCount]; + pointsInit = true; + } + // рисуем фон + g.FillRectangle(Brushes.Aqua, 0, 0, _pictureWidth * _placeSizeWidth, + _pictureHeight * _placeSizeHeight); + + // рисуем основной пирс + g.FillRectangle(Brushes.Gray, 0, 0, _placeSizeWidth * 5 / 4, _placeSizeHeight * 3 / 2); + g.FillRectangle(Brushes.Gray, _pictureWidth - _placeSizeWidth * 5 / 4, 0, + _placeSizeWidth * 5 / 4, _placeSizeHeight * 3 / 2); + + g.FillRectangle(Brushes.Gray, 0, _placeSizeHeight * 3 / 2, + _placeSizeWidth * 1 / 4, _pictureHeight - _placeSizeHeight * 3 / 2); + g.FillRectangle(Brushes.Gray, _pictureWidth - _placeSizeWidth * 1 / 4, _placeSizeHeight * 3 / 2, + _placeSizeWidth * 1 / 4, _pictureHeight - _placeSizeHeight * 3 / 2); + + g.FillRectangle(Brushes.Gray, 0, 0, _pictureWidth, _placeSizeHeight * 1 / 2); + + // рисуем плавучие пирсы + // горизонтальные + int w = _placeSizeWidth; + int h = _placeSizeHeight; + int x = w * 1 / 4; + int y = h * 5 / 2; + int pirsSize = h * 1 / 6; + int i = 0; + while (y + h + pirsSize < _pictureHeight) + { + g.FillRectangle(Brushes.Brown, x, y, w, pirsSize); + g.FillRectangle(Brushes.Brown, _pictureWidth - x - w, y, w, pirsSize); + if (pointsInit) + { + _placesPoints[9 + i] = new Point(x + 5, y - _placeSizeHeight + 5); + _placesPoints[4 - i] = new Point(_pictureWidth - x - w + 5, y - _placeSizeHeight + 5); + } + y += h + pirsSize; + i++; + } + if (pointsInit) + { + _placesPoints[9 + i] = new Point(x + 5, y - _placeSizeHeight + 5); + _placesPoints[4 - i] = new Point(_pictureWidth - x - w + 5, y - _placeSizeHeight + 5); + } + + // вертикальные + x = _placeSizeWidth * 5 / 4 + w; + y = _placeSizeHeight * 1 / 2; + h = _placeSizeHeight; + i = 0; + while (x + w + pirsSize < _pictureWidth - _placeSizeWidth * 5 / 4) + { + g.FillRectangle(Brushes.Brown, x, y, pirsSize, h); + if (pointsInit) + { + _placesPoints[8 - i] = new Point(x - w + 5, y + 5); + } + x += w + pirsSize; + i++; + } + if (pointsInit) + { + _placesPoints[8 - i] = new Point(x - w + 5, y + 5); + } + } + /// + /// Метод отрисовки лодок + /// + /// + private void DrawBoats(Graphics g) + { + for (int i = 0; i < _setBoats.Count; i++) + { + // Установка позиции + _setBoats.Get(i)?.SetObject(_placesPoints[i].X, _placesPoints[i].Y, + _pictureWidth, _pictureHeight); + _setBoats.Get(i)?.DrawingObject(g); + } + } + } +} diff --git a/Boats/Boats/SetBoatsGeneric.cs b/Boats/Boats/SetBoatsGeneric.cs new file mode 100644 index 0000000..b43a073 --- /dev/null +++ b/Boats/Boats/SetBoatsGeneric.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Boats +{ + /// + /// Параметризованный набор объектов + /// + /// + internal class SetBoatsGeneric + where T : class + { + /// + /// Массив объектов, которые храним + /// + private readonly T[] _places; + /// + /// Количество объектов в массиве + /// + public int Count => _places.Length; + /// + /// Конструктор + /// + /// + public SetBoatsGeneric(int count) + { + _places = new T[count]; + } + /// + /// Добавление объекта в набор + /// + /// Добавляемая лодка + /// + public int Insert(T boat) + { + // Вставка в начало набора + return Insert(boat, 0); + } + /// + /// Добавление объекта в набор на конкретную позицию + /// + /// Добавляемая лодка + /// Позиция + /// + public int Insert(T boat, int position) + { + // Проверка позиции + if (position < 0 || position >= _places.Length) + return -1; + // Проверка, что элемент массива по этой позиции пустой + if (_places[position] != null) + { + // Если нет, проверим, что после вставляемого элемента в массиве есть пустой элемент + int i = position + 1; + int nullIndex = -1; + while (i < _places.Length) + { + if (_places[i] == null) + { + nullIndex = i; + break; + } + i++; + } + // Если свободной нет, то выходим + if (nullIndex < 0) + { + return -1; + } + else + { + // Если есть, сдвигаем все объекты, находящиеся + // справа от позиции до первого пустого элемента + i = nullIndex - 1; + while (i >= position) + { + _places[i + 1] = _places[i]; + i--; + } + } + } + // Вставка по позиции + _places[position] = boat; + return position; + } + /// + /// Удаление объекта из набора с конкретной позиции + /// + /// + /// Возвращает удаляемый объект или null, если не удалось удалить + public T Remove(int position) + { + // Проверка позиции + if (position < 0 || position >= _places.Length) + return null; + if (_places[position] == null) + { + return null; + } + // Удаление объекта из массива, присовив элементу массива значение null + T boat = _places[position]; + _places[position] = null; + return boat; + } + /// + /// Получение объекта из набора по позиции + /// + /// + /// Возвращает объект по позиции + public T Get(int position) + { + // Проверка позиции + if (position < 0 || position >= _places.Length) + return null; + return _places[position]; + } + } +}