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];
+ }
+ }
+}