/// <summary> /// Формирует список доступных клеток для "Коня". /// </summary> protected override void FormulatedAvailableActions() { this.CellsForAttacks.Clear(); this.CellsForWalks.Clear(); PointV2[] dirList = { PointV2.down, PointV2.left, PointV2.up, PointV2.right }; PointV2 tmpPoint = new PointV2(this.position.x + 2, this.position.y + 2); foreach (var itemDirList in dirList) { for (int i = 1; i < 5; i++) { tmpPoint += itemDirList; if (i % 2 == 1 && GameBoard.Instance.isOnTheChessboard(tmpPoint)) { if (GetStatusCell(tmpPoint) != side) { CellsForWalks.Add(tmpPoint); } if (base.isCellForAttack(tmpPoint)) { CellsForAttacks.Add(tmpPoint); } } } } }
//private string AbroadChessboardException = "direction не входит в список" + // "координат клеток, доступных для действий. Рекомендуеться использовать координаты из списков CellsForAttacks ии CellsForWalks"; /// <summary> /// Формулирует список координат клеток, с которыми возможно взаимодействие: атака, ход. /// </summary> /// <returns></returns> protected override void FormulatedAvailableActions() { this.CellsForAttacks.Clear(); this.CellsForWalks.Clear(); PointV2 tmpCoordinate; for (int i = 1; i <= CountStep; i++) { tmpCoordinate = new PointV2(this.position.x, this.position.y + i); if (GetStatusCell(tmpCoordinate) == CellStatus.VoidCell) { CellsForWalks.Add(tmpCoordinate); } else { break; } } tmpCoordinate = position + 1; if (isCellForAttack(tmpCoordinate)) { CellsForAttacks.Add(tmpCoordinate); CellsForWalks.Add(tmpCoordinate); } tmpCoordinate = new PointV2(position.x - 1, position.y + 1); if (isCellForAttack(tmpCoordinate)) { CellsForAttacks.Add(tmpCoordinate); CellsForWalks.Add(tmpCoordinate); } }
} // Доступные клетки исключительно для атаки (если таковы имеються) /// <summary> /// Ход на заданую позицию. /// </summary> /// <param name="direction"></param> public virtual void Walk(PointV2 direction) { // Формирует данные о доступных клетках для данной фигуры: ходы, атаки; // для дальнейших проверок. FormulatedAvailableActions(); // == Нет необходимости == if (CellsForWalks.Count > 0) { if (GetIsAvailableForActions(direction)) { //UnityEngine.Debug.LogError("WALk"); if (isCellForAttack(direction)) { //UnityEngine.Debug.LogError("Death"); GameBoard.Instance.GetFigureOfPosition(direction).Death(); } this.position = direction; } else { DontActioEvent("Не возможно выполнить действие относительно клетки по данным координатам"); } } // throw new System.Exception(AbroadChessboardException); //================================================================== else { DontActioEvent("Фигура не имеет ходов"); // СОБЫТИЕ СООБЩАЮЩЕ ЧТО ДАННАЯ ФИГУРА НЕ ИМЕЕТ ДОСТУПНЫХ ХОДОВ } //=================================================================== }
// /// <summary> /// Обработчик события CastlingEvent /// </summary> /// <param name="k"></param> public void Сastle_CastlingEvent(King k) { PointV2 k_position = k.position; k.position = this.position; this.position = k_position; }
public MementoStep(PointV2 position, PointV2 direction, byte index) { CreateArrangementFigures(); this.position = position; this.direction = direction; this.index = index; }
public override void Walk(PointV2 direction) { FormulatedAvailableActions(); if (CellsForWalks.Count > 0) { if (base.GetIsAvailableForActions(direction)) { this.position = direction; if (isFirstStep) { isFirstStep = false; } } else { DontActioEvent("Не возможно выполнить действие относительно клетки по данным координатам"); } } // throw new System.Exception(AbroadChessboardException); //================================================================== else { DontActioEvent("Фигура не имеет ходов"); // СОБЫТИЕ СООБЩАЮЩЕ ЧТО ДАННАЯ ФИГУРА НЕ ИМЕЕТ ДОСТУПНЫХ ХОДОВ } //=================================================================== }
private void CheckShah() { PointV2 kingPos = currentPlayer.Figures.Find(x => x.name == "king").position; foreach (var item in Players[playerIndex - 1].Figures) { if (item.CellsForAttacks.Exists(x => x.Equals(kingPos))) /*Событие шах*/; { } } }
/// <summary> /// Возвращает: доступна ли клетка по заданым координатам для каких либо дейсвтий данной фигуре. /// </summary> /// <param name="direction"></param> /// <returns></returns> public bool GetIsAvailableForActions(PointV2 direction) { if (GameBoard.Instance.isOnTheChessboard(direction) && GetStatusCell(direction) != this.side) { return(true); } else { return(false); } }
/// <summary> /// Возвращат найденую фигуру. Если фигура не найдена, null. /// </summary> /// <param name="pos"></param> /// <returns></returns> public Figure GetFigureOfPosition(PointV2 pos) { if (Figures.Exists(x => x.position.Equals(pos))) { return(Figures.Find(x => x.position.Equals(pos))); } else { return(null); } }
/// <summary> /// Входит ли заданая точка в пределы доски. /// </summary> /// <param name="point"></param> /// <returns></returns> public bool isOnTheChessboard(PointV2 point) { if (point.x <= width && point.x >= zero && point.y <= height && point.y >= zero) { return(true); } else { return(false); } }
/// <summary> /// Если клетка занята фигурой опонента, возвращает true /// </summary> /// <param name="dir"></param> /// <returns></returns> public bool isCellForAttack(PointV2 dir) { CellStatus CS = GetStatusCell(dir); // Если клетка по данным координатам не пуста, входит в границы доски, // сторона фигуры не являеться дружественой - можно ее атаковать. if (this.GetIsAvailableForActions(dir) && CS != CellStatus.VoidCell) { return(true); } else { return(false); } }
/// <summary> /// Сравнивает экземпляры структуры PointV2, по значению. /// </summary> /// <param name="obj"></param> /// <returns></returns> public override bool Equals(object obj) { if (obj == null) { return(false); } PointV2 tmp = (PointV2)obj; if (x == tmp.x && y == tmp.y) { return(true); } else { return(false); } }
/// <summary> /// Возвращает список доступных клеток относительно текущей позиции фигуры, в указаном направлении. /// </summary> /// <param name="figure"></param> /// <param name="dir"></param> /// <returns></returns> static private List <PointV2> BustPoints(IMotionInterfaceFigure figure, PointV2 dir) { // Временно значение точки изменяемое каждую итерацию. PointV2 BufferPoint, // Позиция фигуры относительно которой вычисляються точки. position = figure.position; List <PointV2> result = new List <PointV2>(); // Вычисление начальной точки, с которой будет вестись последующие вычисления. // Позиция фигуры не учитываеться !!! BufferPoint = position + dir; // Все вычисление ведутся пока точка находиться в пределах игровой доски. while (GameBoard.Instance.isOnTheChessboard(BufferPoint)) { // Еслм точка выходит за границу доски - выход из цыкла. if (!GameBoard.Instance.isOnTheChessboard(BufferPoint)) { break; } // Если фигуре доступен шаг на текушую точку 'BufferPoint', добавляем в список-результат. // Интерфейс IMotionInterfaceFigure предоставляет метод который содержит каждая фигура // и который определяет доступна ли точка для шага данной фигуры. if (figure.GetIsAvailableForActions(BufferPoint)) { result.Add(BufferPoint); // Шаг в заданом направлении. BufferPoint += dir; } // Если точка недоступна, все последующие так же не доступны по правилам шахмат. // выход из цыкла. // Данное правило обходит только фигуру'конь'. else { break; } } return(result); }
/// <summary> /// Возвращает статус клетки: Сторона игрока, пустая клетка, координата вышла за границу доски. /// </summary> /// <param name="direction"></param> /// <returns></returns> protected CellStatus GetStatusCell(PointV2 direction) { // Если клетка входит в границы игрового поля. if (GameBoard.Instance.isOnTheChessboard(direction)) { // Если на игровой доске есть фигура с задаными координатами, возвращаем ее статус. if (GameBoard.Instance.Figures.Exists(x => x.position.Equals(direction))) { return(GameBoard.Instance.Figures.Find(x => x.position.Equals(direction)).side); } // Иначе клетка пустая. else { return(CellStatus.VoidCell); } } else { return(CellStatus.AbroadChessboard); } }
/// <summary> /// Возвращает список доступных клеток в один шаг, относительно текущей позиции фигуры, в указаном направлении. /// </summary> /// <param name="figure"></param> /// <param name="dir"></param> /// <param name="isOneStep"></param> /// <returns></returns> static private List <PointV2> BustPoints(IMotionInterfaceFigure figure, PointV2 dir, bool isOneStep) { // Временно значение точки изменяемое каждую итерацию. PointV2 BufferPoint, // Позиция фигуры относительно которой вычисляються точки. position = figure.position; List <PointV2> result = new List <PointV2>(); //Вычисление начальной точки, с которой будет вестись последующие вычисления. BufferPoint = position + dir; // Если фигуре доступен шаг на текушую точку 'BufferPoint', добавляем в список-результат. // Интерфейс IMotionInterfaceFigure предоставляет метод который содержит каждая фигура // и который определяет доступна ли точка для шага данной фигуры. if (figure.GetIsAvailableForActions(BufferPoint)) { result.Add(BufferPoint); } // Данная функция возвращает по сути лишь одну точку, один шаг. // Поэтому возвращаем результат, после вычисления. return(result); }
public Figure GeFigure(PointV2 pos) { return(Figures.Find(x => x.Equals(pos))); }
public void SaveStep(PointV2 position, PointV2 direction, CellStatus side) { Hystory.Add(new MementoStep(position, direction, (byte)(Hystory.Count + 1))); }
public Figure(CellStatus side, PointV2 position) { this.position = position; this.side = side; this.Initialize(); }
public Сastle(CellStatus side, PointV2 position) : base(side, position) { }
public Horse(CellStatus side, PointV2 position) : base(side, position) { }
public King(CellStatus side, PointV2 position) : base(side, position) { }
public Pawn(CellStatus side, PointV2 position) : base(side, position) { isFirstStep = true; }
/// <summary> /// Возвращает список клеток по диагонале А - прямая линия относительно текущей позиции состоящая из множества клеток, /// соединющих углы (нижний левый - верхний парвый) условной матрицы , которой являеться игровое поле. /// </summary> /// <param name="figure"></param> /// <param name="isOneStep"></param> /// <returns></returns> public static List <PointV2> GetDiagonaleA(IMotionInterfaceFigure figure, bool isOneStep) { #region messy code //List<PointV2> result = new List<PointV2>(); //PointV2 BufferPoint = new PointV2(); //// Длинна диагонали //int diagonaleLenght = 0; //// Вычисление diagonaleLenght //if (position.x < position.y) // diagonaleLenght = GameBoard.Instance.height + position.x - position.y; //else if (position.x > position.y & position.x != position.y) // diagonaleLenght = GameBoard.Instance.height + position.y - position.x; //else diagonaleLenght = GameBoard.Instance.height; //// Если х <= у параметра position, начальная точка ( 1 по х, у длинна диагонали). //// if (position.x <= position.y) //BufferPoint = new PointV2(GameBoard.Instance.zero, diagonaleLenght); //// Иначе начальная точка ( ширина игровой доски - (длинна диагонали - 1), у 1). //// Тоесть, начальная точка что лежит на побочной диагонали, если! она ниже основной. //// НЕОБХОДИМО ТЕСТИРОВАТЬ. //// else ///// BufferPoint = new PointV2(GameBoard.Instance.width - (diagonaleLenght - 1), GameBoard.Instance.zero); //while (GameBoard.Instance.isOnTheChessboard(BufferPoint)) //{ // result.Add(BufferPoint); // BufferPoint += PointV2.up + PointV2.right; // if (!GameBoard.Instance.isOnTheChessboard(BufferPoint)) // break; //} //return result; #endregion // FIX // Направление вниз и влево. PointV2 dirDownAndLeft = (PointV2.down + PointV2.left), // Направление вверх и вправо dirUpAndright = (PointV2.up + PointV2.right); List <PointV2> result = new List <PointV2>(); // Добавляет к результату, множества точек, относительно заданых параметров. if (!isOneStep) { result.AddRange(BustPoints(figure, dirDownAndLeft)); result.AddRange(BustPoints(figure, dirUpAndright)); } // Добавляет к результату один шаг, относительно заданых параметров. else { result.AddRange(BustPoints(figure, dirDownAndLeft, isOneStep)); result.AddRange(BustPoints(figure, dirUpAndright, isOneStep)); } return(result); }