diff --git a/ProjectExcavator/ProjectExcavator/AbstractStrategy.cs b/ProjectExcavator/ProjectExcavator/AbstractStrategy.cs new file mode 100644 index 0000000..f33ed01 --- /dev/null +++ b/ProjectExcavator/ProjectExcavator/AbstractStrategy.cs @@ -0,0 +1,134 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + + +namespace ProjectExcavator.MovementStrategy +{ + /// + /// Класс-стратегия перемещения объекта + /// + public abstract class AbstractStrategy + { + /// + /// Перемещаемый объект + /// + private IMoveableObject? _moveableObject; + /// + /// Статус перемещения + /// + private Status _state = Status.NotInit; + /// + /// Ширина поля + /// + protected int FieldWidth { get; private set; } + /// + /// Высота поля + /// + protected int FieldHeight { get; private set; } + /// + /// Статус перемещения + /// + public Status GetStatus() { return _state; } + /// + /// Установка данных + /// + /// Перемещаемый объект + /// Ширина поля + /// Высота поля + public void SetData(IMoveableObject moveableObject, int width, int height) + { + if (moveableObject == null) + { + _state = Status.NotInit; + return; + } + _state = Status.InProgress; + _moveableObject = moveableObject; + FieldWidth = width; + FieldHeight = height; + } + /// + /// Шаг перемещения + /// + public void MakeStep() + { + if (_state != Status.InProgress) + { + return; + } + if (IsTargetDestination()) + { + _state = Status.Finish; + return; + } + MoveToTarget(); + } + /// + /// Перемещение влево + /// + /// Результат перемещения (true - удалось переместиться, false - неудача) + protected bool MoveLeft() => MoveTo(DirectionType.Left); + /// + /// Перемещение вправо + /// + /// Результат перемещения (true - удалось переместиться, false - неудача) + protected bool MoveRight() => MoveTo(DirectionType.Right); + /// + /// Перемещение вверх + /// + /// Результат перемещения (true - удалось переместиться, false - неудача) + protected bool MoveUp() => MoveTo(DirectionType.Up); + /// + /// Перемещение вниз + /// + /// Результат перемещения (true - удалось переместиться, false - неудача) + protected bool MoveDown() => MoveTo(DirectionType.Down); + /// + /// Параметры объекта + /// + protected ObjectParameters? GetObjectParameters => _moveableObject?.GetObjectPosition; + /// + /// Шаг объекта + /// + /// + protected int? GetStep() + { + if (_state != Status.InProgress) + { + return null; + } + return _moveableObject?.GetStep; + } + /// + /// Перемещение к цели + /// + protected abstract void MoveToTarget(); + /// + /// Достигнута ли цель + /// + /// + protected abstract bool IsTargetDestination(); + /// + /// Попытка перемещения в требуемом направлении + /// + /// Направление + /// Результат попытки (true - удалось переместиться, false - неудача) + private bool MoveTo(DirectionType directionType) + { + if (_state != Status.InProgress) + { + return false; + } + if (_moveableObject?.CheckCanMove(directionType) ?? false) + { + _moveableObject.MoveObject(directionType); + return true; + } + return false; + } + + } +} diff --git a/ProjectExcavator/ProjectExcavator/DrawningExcavarorBodyKits.cs b/ProjectExcavator/ProjectExcavator/DrawningExcavarorBodyKits.cs index 7271fda..79f4a78 100644 --- a/ProjectExcavator/ProjectExcavator/DrawningExcavarorBodyKits.cs +++ b/ProjectExcavator/ProjectExcavator/DrawningExcavarorBodyKits.cs @@ -43,8 +43,9 @@ namespace ProjectExcavator.DrawningObjects //ыспомогательные опоры if (excavator.BodyKit) { - + g.FillRectangle(additionalBrush, _startPosX + 20, _startPosY + 100, 110, 10); } + //отрисовка базы экскаватора base.DrawTransport(g); //ковш if (excavator.Bucket) diff --git a/ProjectExcavator/ProjectExcavator/DrawningExcavator.cs b/ProjectExcavator/ProjectExcavator/DrawningExcavator.cs index e5e90d3..76870f1 100644 --- a/ProjectExcavator/ProjectExcavator/DrawningExcavator.cs +++ b/ProjectExcavator/ProjectExcavator/DrawningExcavator.cs @@ -32,11 +32,26 @@ namespace ProjectExcavator.DrawningObjects /// /// Ширина прорисовки автомобиля /// - protected readonly int _excavatorWidth = 100; + protected readonly int _excavatorWidth = 150; /// /// Высота прорисовки автомобиля /// - protected readonly int _excavatorHeight = 55; + protected readonly int _excavatorHeight = 155; + /// + /// Координата X объекта + /// + public int GetPosX => _startPosX; + /// + /// Координата Y объекта + /// + public int GetPosY => _startPosY; + /// Ширина объекта + /// + public int GetWidth => _excavatorWidth; + /// + /// Высота объекта + /// + public int GetHeight => _excavatorHeight; /// /// Конструктор /// @@ -87,12 +102,36 @@ namespace ProjectExcavator.DrawningObjects _startPosY = y; } /// + /// Проверка, что объект может переместится по указанному направлению + /// + /// Направление + /// true - можно переместится по указанному направлению + public bool CanMove(DirectionType direction) + { + if(EntityExcavator == null) + { + return false; + } + return direction switch + { + //влево + DirectionType.Left => _startPosX - EntityExcavator.Step >0, + //вверх + DirectionType.Up => _startPosY - EntityExcavator.Step > -50, + //вправо + DirectionType.Right => _startPosX + EntityExcavator.Step < _pictureWidth - _excavatorWidth, + //вниз + DirectionType.Down => _startPosY + EntityExcavator.Step < _pictureHeight - _excavatorHeight, + _ => false, + }; + } + /// /// Изменение направления перемещения /// /// Направление public void MoveTransport(DirectionType direction) { - if (EntityExcavator == null) + if (!CanMove(direction) || EntityExcavator == null) { return; } @@ -100,31 +139,19 @@ namespace ProjectExcavator.DrawningObjects { //влево case DirectionType.Left: - if (_startPosX - EntityExcavator.Step > 0) - { - _startPosX -= (int)EntityExcavator.Step; - } + _startPosX -= (int)EntityExcavator.Step; break; //вверх case DirectionType.Up: - if (_startPosY - EntityExcavator.Step > 0) - { - _startPosY -= (int)EntityExcavator.Step; - } + _startPosY -= (int)EntityExcavator.Step; break; // вправо case DirectionType.Right: - if (_startPosX + EntityExcavator.Step < _pictureWidth - _excavatorWidth) - { - _startPosX += (int)EntityExcavator.Step; - } + _startPosX += (int)EntityExcavator.Step; break; //вниз case DirectionType.Down: - if (_startPosY + EntityExcavator.Step < _pictureHeight - _excavatorHeight) - { - _startPosY += (int)EntityExcavator.Step; - } + _startPosY += (int)EntityExcavator.Step; break; } } diff --git a/ProjectExcavator/ProjectExcavator/DrawningObjectExcavator.cs b/ProjectExcavator/ProjectExcavator/DrawningObjectExcavator.cs new file mode 100644 index 0000000..5465b87 --- /dev/null +++ b/ProjectExcavator/ProjectExcavator/DrawningObjectExcavator.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using ProjectExcavator.DrawningObjects; + +namespace ProjectExcavator.MovementStrategy +{ + /// + /// Реализация интерфейса IDrawningObject для работы с объектом DrawningCar (паттерн Adapter) + /// + public class DrawningObjectExcavator : IMoveableObject + { + private readonly DrawningExcavator? _drawningExcavator = null; + public DrawningObjectExcavator(DrawningExcavator drawningExcavator) + { + _drawningExcavator = drawningExcavator; + } + public ObjectParameters? GetObjectPosition + { + get + { + if(_drawningExcavator == null || _drawningExcavator.EntityExcavator == null) + { + return null; + } + return new ObjectParameters(_drawningExcavator.GetPosX, + _drawningExcavator.GetPosY, + _drawningExcavator.GetWidth, + _drawningExcavator.GetHeight); + } + } + public int GetStep => (int)(_drawningExcavator?.EntityExcavator?.Step ?? 0); + + public bool CheckCanMove(DirectionType direction) =>_drawningExcavator?.CanMove(direction) ?? false; + + public void MoveObject(DirectionType direction) => _drawningExcavator?.MoveTransport(direction); + } +} diff --git a/ProjectExcavator/ProjectExcavator/EntityExcavatorBodyKits.cs b/ProjectExcavator/ProjectExcavator/EntityExcavatorBodyKits.cs index d9f7403..2994917 100644 --- a/ProjectExcavator/ProjectExcavator/EntityExcavatorBodyKits.cs +++ b/ProjectExcavator/ProjectExcavator/EntityExcavatorBodyKits.cs @@ -4,6 +4,8 @@ using System.Linq; using System.Net.NetworkInformation; using System.Text; using System.Threading.Tasks; +using ProjectExcavator.Entities; + namespace ProjectExcavator.Entities { @@ -38,7 +40,7 @@ namespace ProjectExcavator.Entities Color bodyColor, Color additionalColor, bool bodyKit, - bool bucket) + bool bucket) : base(speed, weight, bodyColor) { AdditionalColor = additionalColor; BodyKit = bodyKit; diff --git a/ProjectExcavator/ProjectExcavator/ExcavatorForm.Designer.cs b/ProjectExcavator/ProjectExcavator/ExcavatorForm.Designer.cs index e7b1f13..39c5858 100644 --- a/ProjectExcavator/ProjectExcavator/ExcavatorForm.Designer.cs +++ b/ProjectExcavator/ProjectExcavator/ExcavatorForm.Designer.cs @@ -34,6 +34,9 @@ buttonUp = new Button(); buttonLeft = new Button(); buttonRight = new Button(); + comboBoxStrategy = new ComboBox(); + buttonCreateExcavatorBodyKits = new Button(); + buttonStep = new Button(); ((System.ComponentModel.ISupportInitialize)pictureBoxExcavator).BeginInit(); SuspendLayout(); // @@ -50,11 +53,11 @@ // buttonCreate // buttonCreate.Anchor = AnchorStyles.Bottom | AnchorStyles.Left; - buttonCreate.Location = new Point(12, 415); + buttonCreate.Location = new Point(12, 397); buttonCreate.Name = "buttonCreate"; - buttonCreate.Size = new Size(75, 23); + buttonCreate.Size = new Size(155, 41); buttonCreate.TabIndex = 1; - buttonCreate.Text = "Создать"; + buttonCreate.Text = "Создать простой экскаватор"; buttonCreate.UseVisualStyleBackColor = true; buttonCreate.Click += buttonCreate_Click; // @@ -106,11 +109,44 @@ buttonRight.UseVisualStyleBackColor = true; buttonRight.Click += buttonMove_Click; // + // comboBoxStrategy + // + comboBoxStrategy.DropDownStyle = ComboBoxStyle.DropDownList; + comboBoxStrategy.FormattingEnabled = true; + comboBoxStrategy.Items.AddRange(new object[] { "0", "1" }); + comboBoxStrategy.Location = new Point(667, 12); + comboBoxStrategy.Name = "comboBoxStrategy"; + comboBoxStrategy.Size = new Size(121, 23); + comboBoxStrategy.TabIndex = 6; + // + // buttonCreateExcavatorBodyKits + // + buttonCreateExcavatorBodyKits.Location = new Point(173, 397); + buttonCreateExcavatorBodyKits.Name = "buttonCreateExcavatorBodyKits"; + buttonCreateExcavatorBodyKits.Size = new Size(145, 41); + buttonCreateExcavatorBodyKits.TabIndex = 7; + buttonCreateExcavatorBodyKits.Text = "Создать Экскаватор с обвесами"; + buttonCreateExcavatorBodyKits.UseVisualStyleBackColor = true; + buttonCreateExcavatorBodyKits.Click += buttonCreateExcavatorBodyKits_Click; + // + // buttonStep + // + buttonStep.Location = new Point(713, 41); + buttonStep.Name = "buttonStep"; + buttonStep.Size = new Size(75, 23); + buttonStep.TabIndex = 8; + buttonStep.Text = "Шаг"; + buttonStep.UseVisualStyleBackColor = true; + buttonStep.Click += buttonStep_Click; + // // ExcavatorForm // AutoScaleDimensions = new SizeF(7F, 15F); AutoScaleMode = AutoScaleMode.Font; ClientSize = new Size(800, 450); + Controls.Add(buttonStep); + Controls.Add(buttonCreateExcavatorBodyKits); + Controls.Add(comboBoxStrategy); Controls.Add(buttonRight); Controls.Add(buttonLeft); Controls.Add(buttonUp); @@ -133,5 +169,8 @@ private Button buttonUp; private Button buttonLeft; private Button buttonRight; + private ComboBox comboBoxStrategy; + private Button buttonCreateExcavatorBodyKits; + private Button buttonStep; } } \ No newline at end of file diff --git a/ProjectExcavator/ProjectExcavator/ExcavatorForm.cs b/ProjectExcavator/ProjectExcavator/ExcavatorForm.cs index 6b7455f..c8a16f1 100644 --- a/ProjectExcavator/ProjectExcavator/ExcavatorForm.cs +++ b/ProjectExcavator/ProjectExcavator/ExcavatorForm.cs @@ -1,3 +1,6 @@ +using ProjectExcavator.DrawningObjects; +using ProjectExcavator.MovementStrategy; + namespace ProjectExcavator { public partial class ExcavatorForm : Form @@ -7,6 +10,10 @@ namespace ProjectExcavator /// private DrawningExcavator? _drawnigExcavator; /// + /// + /// + private AbstractStrategy? _abstractStrategy; + /// /// /// public ExcavatorForm() @@ -41,17 +48,12 @@ namespace ProjectExcavator private void buttonCreate_Click(object sender, EventArgs e) { Random random = new(); - _drawnigExcavator = new DrawningExcavator(); - _drawnigExcavator.Init(random.Next(100, 300), + _drawnigExcavator = new DrawningExcavator( + random.Next(100, 300), random.Next(1000, 3000), Color.FromArgb(random.Next(0, 256), random.Next(0, 256), random.Next(0, 256)), - Color.FromArgb(random.Next(0, 256), random.Next(0, 256), random.Next(0, 256)), - Convert.ToBoolean(random.Next(0, 2)), - Convert.ToBoolean(random.Next(0, 2)), pictureBoxExcavator.Width, pictureBoxExcavator.Height); - _drawnigExcavator.SetPosition(random.Next(10, 100), - random.Next(10, 100)); Draw(); } private void buttonMove_Click(object sender, EventArgs e) @@ -78,5 +80,56 @@ namespace ProjectExcavator } Draw(); } + + private void buttonCreateExcavatorBodyKits_Click(object sender, EventArgs e) + { + Random random = new(); + _drawnigExcavator = new DrawningExcavarorBodyKits(random.Next(100, 300), + random.Next(1000, 3000), + Color.FromArgb(random.Next(0, 256), random.Next(0, 256), random.Next(0, 256)), + Color.FromArgb(random.Next(0, 256), random.Next(0, 256), random.Next(0, 256)), + Convert.ToBoolean(random.Next(0, 2)), + Convert.ToBoolean(random.Next(0, 2)), + pictureBoxExcavator.Width, + pictureBoxExcavator.Height); + _drawnigExcavator.SetPosition(random.Next(10, 100), random.Next(10, 100)); + Draw(); + } + + private void buttonStep_Click(object sender, EventArgs e) + { + if (_drawnigExcavator == null) + { + return; + } + if (comboBoxStrategy.Enabled) + { + _abstractStrategy = comboBoxStrategy.SelectedIndex switch + { + 0 => new MoveToCenter(), + 1 => new MoveToBorder(), + _ => null, + }; + if (_abstractStrategy == null) + { + return; + } + _abstractStrategy.SetData(new DrawningObjectExcavator(_drawnigExcavator), + pictureBoxExcavator.Width, + pictureBoxExcavator.Height); + comboBoxStrategy.Enabled = false; + } + if (_abstractStrategy == null) + { + return; + } + _abstractStrategy.MakeStep(); + Draw(); + if (_abstractStrategy.GetStatus() == Status.Finish) + { + comboBoxStrategy.Enabled = true; + _abstractStrategy = null; + } + } } } \ No newline at end of file diff --git a/ProjectExcavator/ProjectExcavator/IMoveableObject.cs b/ProjectExcavator/ProjectExcavator/IMoveableObject.cs new file mode 100644 index 0000000..fc48d19 --- /dev/null +++ b/ProjectExcavator/ProjectExcavator/IMoveableObject.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ProjectExcavator.MovementStrategy +{ + /// + /// Интерфейс для работы с перемещаемым объектом + /// + public interface IMoveableObject + { + /// + /// Получение координаты X объекта + /// + ObjectParameters? GetObjectPosition { get; } + /// + /// Шаг объекта + /// + int GetStep { get; } + /// + /// Проверка, можно ли переместиться по нужному направлению + /// + /// + /// + bool CheckCanMove(DirectionType direction); + /// + /// Изменение направления пермещения объекта + /// + /// Направление + void MoveObject(DirectionType direction); + } +} diff --git a/ProjectExcavator/ProjectExcavator/MoveToBorder.cs b/ProjectExcavator/ProjectExcavator/MoveToBorder.cs new file mode 100644 index 0000000..7fbe879 --- /dev/null +++ b/ProjectExcavator/ProjectExcavator/MoveToBorder.cs @@ -0,0 +1,49 @@ +using ProjectExcavator.Entities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ProjectExcavator.MovementStrategy +{ + public class MoveToBorder : AbstractStrategy + { + protected override bool IsTargetDestination() + { + var objParams = GetObjectParameters; + if(objParams == null) + { + return false; + } + return objParams.RightBorder + GetStep() >= FieldWidth && objParams.DownBorder + + GetStep() <= FieldHeight; + } + protected override void MoveToTarget() + { + var objParams = GetObjectParameters; + if(objParams == null) + { + return; + } + var diffX = objParams.RightBorder - FieldWidth - 150; + var diffY = objParams.DownBorder - FieldHeight - 150; + if(diffX >= 0) + { + MoveDown(); + } + else if (diffY >= 0) + { + MoveRight(); + } + else if(Math.Abs(diffX) > Math.Abs(diffY)) + { + MoveRight(); + } + else + { + MoveDown(); + } + } + } +} diff --git a/ProjectExcavator/ProjectExcavator/MoveToCenter.cs b/ProjectExcavator/ProjectExcavator/MoveToCenter.cs new file mode 100644 index 0000000..8c32d3f --- /dev/null +++ b/ProjectExcavator/ProjectExcavator/MoveToCenter.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ProjectExcavator.MovementStrategy +{ + public class MoveToCenter : AbstractStrategy + { + protected override bool IsTargetDestination() + { + var objParams = GetObjectParameters; + if (objParams == null) + { + return false; + } + return objParams.ObjectMiddleHorizontal <= FieldWidth / 2 && + objParams.ObjectMiddleHorizontal + GetStep() >= FieldWidth / 2 && + objParams.ObjectMiddleVertical <= FieldHeight / 2 && + objParams.ObjectMiddleVertical + GetStep() >= FieldHeight / 2; + + } + protected override void MoveToTarget() + { + var objParams = GetObjectParameters; + if (objParams == null) + { + return; + } + var diffX = objParams.ObjectMiddleHorizontal - FieldWidth / 2; + if (Math.Abs(diffX) > GetStep()) + { + if (diffX > 0) + { + MoveLeft(); + } + else + { + MoveRight(); + } + } + var diffY = objParams.ObjectMiddleVertical - FieldHeight / 2; + if (Math.Abs(diffY) > GetStep()) + { + if (diffY > 0) + { + MoveUp(); + } + else + { + MoveDown(); + } + } + } + } +} diff --git a/ProjectExcavator/ProjectExcavator/ObjectParameters.cs b/ProjectExcavator/ProjectExcavator/ObjectParameters.cs new file mode 100644 index 0000000..c78c2e1 --- /dev/null +++ b/ProjectExcavator/ProjectExcavator/ObjectParameters.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ProjectExcavator.MovementStrategy +{ + public class ObjectParameters + { + private readonly int _x; + 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/ProjectExcavator/ProjectExcavator/Status.cs b/ProjectExcavator/ProjectExcavator/Status.cs new file mode 100644 index 0000000..8f61c75 --- /dev/null +++ b/ProjectExcavator/ProjectExcavator/Status.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ProjectExcavator +{ + public enum Status + { + NotInit = 0, + InProgress = 1, + Finish = 2 + } +}