/// <summary> /// Конструктор класса /// </summary> /// <param name="parPosition">Положение на поле</param> /// <param name="parFirstHole">Первое отверстие </param> /// <param name="parSecondHole">Второе отверстие</param> /// <param name="parImage">Изображение трубы</param> public Pipe(Point parPosition, Orientation parFirstHole, Orientation parSecondHole, Bitmap parImage) { _Position = parPosition; _FirstHole = parFirstHole; _SecondHole = parSecondHole; _Image = parImage; _PartOfPath = false; }
private bool DepthSolve(Point parCurrentPoint, Orientation parDirection, SolutionThree parSolutionNode) { //решение еще не найдено bool complete = false; //добавляем узел в дерево решений SolutionThree solutionThree = parSolutionNode; //назначаем текущую точку Point currentPoint = parCurrentPoint; //назначаем направление движения Orientation direction = parDirection; //исходя из текущего положения и направления движения вычисляем следующую точку Point nextPoint = new Point(currentPoint.X + direction.X, currentPoint.Y + direction.Y); //Если следующая точка является точкой выхода, if (nextPoint == _Exit) { //то решение найдено, алгоритм завершен complete = true; } //если текущая труба вывела нас за границы поля else if ((nextPoint.X < 1) || (nextPoint.X > _ColCount) || (nextPoint.Y < 1) || (nextPoint.Y > _RowCount)) { //тупик complete = false; } else { //если в следующей точки нету трубы if ((object) _Field[nextPoint.X, nextPoint.Y] == null) { //тупик complete = false; } //если в ледующей точке есть труба, то смотрим ее else { //если следующая труба уже задействована в текущем рассматриваемом пути, if (_Field[nextPoint.X, nextPoint.Y].PartOfPath == true) { //тупик complete = false; } //если следующая труба еще не задействована else { //получаем следующую трубу Pipe nextPipe = _Field[nextPoint.X, nextPoint.Y]; //разворачиваем ее так, какой-то из ее входов выходил на текущую точку nextPipe.RotateTo(currentPoint); //добавляем в дерево решений новую ветку рассмотрения solutionThree.AddChildNode(nextPipe.Clone(), currentPoint); //получаем новое направление движение (куда смотрит второй вход следующей трубы) Orientation nextDirection = direction; if (direction == -nextPipe.FirstHole) { nextDirection = nextPipe.SecondHole.Clone(); } else { nextDirection = nextPipe.FirstHole.Clone(); } //помечаем, что труба занята в решении nextPipe.PartOfPath = true; //вызываем рекурсивный методи рассматриваем все со следующей точки со следующим направлением complete = DepthSolve(nextPoint, nextDirection, solutionThree.ChildNodes[0]); //если поиск в глубину завершился неудачей и поворачивать еще можно //(т.е. следующая труба не прямая, ведь ее разворот приведет к томуже результату) if ((complete == false) && (nextPipe.FirstHole != -nextPipe.SecondHole)) { //удаляем текущую ветвь дерева решений solutionThree.ChildNodes.RemoveAt(0); //поворачиваем трубу второй раз, другим входом к текущей точке nextPipe.RotateTo(currentPoint); //добавляем в дерево решений новую ветвь solutionThree.AddChildNode(nextPipe, currentPoint); //вычисляем новое направление движения if (direction == -nextPipe.FirstHole) { nextDirection = nextPipe.SecondHole; } else { nextDirection = nextPipe.FirstHole; } //и вызываем поиск в глубину в новом направлении (это уже второй вызов) complete = DepthSolve(nextPoint, nextDirection, solutionThree.ChildNodes[0]); //если и в эту сторону решение не находится if (complete == false) { //то следующая труба - безперспективна nextPipe.PartOfPath = false; } } } } } return complete; }