/// <summary> /// Конструктор /// </summary> /// <param name="parRoot">Родиельский узел</param> /// <param name="parLevel">Уровень</param> public SolutionThree(Move parMove, SolutionThree parRoot, int parLevel) { _Root = parRoot; _Level = parLevel; _Move = parMove; _ChildNodes = new List<SolutionThree>(); }
/// <summary> /// Добавить дочерний узел в дерево /// </summary> /// <param name="parMove"></param> public void AddChildNode(Move parMove) { _ChildNodes.Add(new SolutionThree(parMove, this, _Level + 1)); }
/// <summary> /// Отмена хода /// </summary> /// <param name="parMove"></param> /// <param name="parSolutionThree"></param> public override void CancelMove(Move parMove, SolutionThree parSolutionThree) { _Task.Mirrors = parMove.Mirrors; for (int i = 0; i < _Task.Mirrors.Count; i++) { if ((_Task.Mirrors[i].Left == parMove.ToPos.X) && (_Task.Mirrors[i].Top == parMove.ToPos.Y)) { parMove.Mirrors[i] = new Square(parMove.FromPos.Y, parMove.FromPos.Y + LasersGame.COORDINATE_RATIO, parMove.FromPos.X, parMove.FromPos.X + LasersGame.COORDINATE_RATIO); _Task.CalculateLaser(); } } }
/// <summary> /// Оценочная функция /// </summary> /// <param name="parMove">оцениваемый ход</param> /// <param name="parSolutionThree"> узелд дерева из которого совершается ход</param> /// <returns>rколичество ходов, прошедших с момента последненго перемещения зеркала, указанного в ходе</returns> public override int Estimator(Move parMove, SolutionThree parSolutionThree) { int rating = MaxAlowableDepth + 1; //получаем исходное положение перемещаемого зеркала Point mirrorPosition = parMove.FromPos; //и узел дерева из которого совершаем ход SolutionThree solutionNode = parSolutionThree; //пока не добрались до корня дерва поиска while (solutionNode.Root != null) { //если ход, приведший к текущему узлу дерева, перемещал проверяемое зеркало if (solutionNode.Move.ToPos == mirrorPosition) { //считаем сколько ходов назад это было rating = parSolutionThree.Level - solutionNode.Level + 1; break; } //иначе else { //и перемещаемся вверх по дереву. solutionNode = solutionNode.Root; } } return rating; }
/// <summary> /// Совершение хода /// </summary> /// <param name="parMove">Совершаемый ход</param> /// <param name="parSolutionThree">узел дерева, из которого совершаем ход</param> public override void MakeMove(Move parMove, SolutionThree parSolutionThree) { //активизируем поле _Task.Mirrors = GetMirrorsCopy(parMove.Mirrors); //проходим по всем зеркалам for (int i = 0; i < _Task.Mirrors.Count; i++) { //находим зеркало указанное в ходе и совершием ход if ((_Task.Mirrors[i].Left == parMove.FromPos.X) && (_Task.Mirrors[i].Top == parMove.FromPos.Y)) { parMove.Mirrors[i] = new Square(parMove.ToPos.Y, parMove.ToPos.Y + LasersGame.COORDINATE_RATIO, parMove.ToPos.X, parMove.ToPos.X + LasersGame.COORDINATE_RATIO); } } _Task.Mirrors = GetMirrorsCopy(parMove.Mirrors); //пересчитываем траекторию лазера _Task.CalculateLaser(); }
/// <summary> /// Создать первый ход /// </summary> /// <returns></returns> public override Move CreateFirstMove() { Move firstMove = null; if (_Task.Mirrors.Count > 0) { firstMove = new Move(new Point(-1,-1), new Point (-1,-1), GetMirrorsCopy(_Task.Mirrors)); } return firstMove; }
/// <summary> /// Поиск по градиенту /// </summary> /// <param name="parMove">Ход</param> /// <param name="parSolutionThree">дерево решений</param> /// <returns>true если решение найдено, false в противном случае</returns> public bool SteepestRiseSolve(Move parMove, SolutionThree parSolutionThree) { //решение еще не найдено bool complete = false; //дерево решений SolutionThree solutionThree = parSolutionThree; //последний совершенный ход Move lastMove = solutionThree.Move; //если цель достигнута if (GoalIsReached(solutionThree)) { complete = true; //записываем длину пути и получаем список ходов _Info.PathLenght = solutionThree.Level; _Info.MovesToGoal = GetMovesToGoal(solutionThree); } else // ессли тупик if (Deadlock(solutionThree)) { complete = false; } //если цель не достигнута и ситуация не тупиковая else { //получаем список возможных ходщв List<Move> availableMoves = GetAvailableMoves(solutionThree); //упорядочиваем список возможных ходов согласно оценочной функции SortMoves(availableMoves, solutionThree); //проходим по всем узлам for (int i = 0; i < availableMoves.Count; i++) { //совершаем очередной ход MakeMove(availableMoves[i], solutionThree); //добавляем узел в дерево решений solutionThree.AddChildNode(availableMoves[i]); _Info.GeneratedNodesCount++; //Если уровень узла нового узла дерева больше чем сохраненный в логе, if (solutionThree.ChildNodes[0].Level > _Info.MaxDepth) { //то записываем его в лог _Info.MaxDepth = solutionThree.ChildNodes[0].Level; } // вызываем рекурсивный метод поиска в глубину complete = SteepestRiseSolve(availableMoves[i], solutionThree.ChildNodes[0]); //если решение было найдено if (complete) { //заканчиваем просмотр break; } //в противном случае else { //отменяем ход и удаляем рассмотренную ветку дерева CancelMove(availableMoves[i], solutionThree); solutionThree.DeleteChildNode(0); } } } //возвращаем результат выполнения return complete; }
/// <summary> /// Совершение хода /// </summary> /// <param name="parMove">Ход</param> /// <param name="parSolutionThree"> узелд дерева из которого совершается ход</param> public abstract void MakeMove(Move parMove, SolutionThree parSolutionThree);
/// <summary> /// Оценочная функция /// </summary> /// <param name="parMove">оцениваемый ход</param> /// <param name="parSolutionThree"> узелд дерева из которого совершается ход</param> /// <returns>оценка хода</returns> public abstract int Estimator(Move parMove, SolutionThree parSolutionThree);
/// <summary> /// Отмена хода /// </summary> /// <param name="parMove">Ход</param> /// <param name="parSolutionThree">узел дерева у которого отменяется ход</param> public abstract void CancelMove(Move parMove, SolutionThree parSolutionThree);