/// <summary> /// конструктор наследования/углубления /// реализует один из возможных ходов родительской доски /// </summary> public Three(Three a, int moveNumber) { _countThree++; this._parent = a;//породивший узел называется родителем Move[] MovesAvailable = a._movesAvailable; if ((MovesAvailable != null) && (MovesAvailable.Length > moveNumber)) { this._boardMoved = Board.DoMove(a._boardMoved, MovesAvailable[moveNumber]); } this._move = MovesAvailable[moveNumber]; //this._valueMax = -1000; //this._valueMin = 1000; this._depth = a._depth + 1; this._movesAvailable = Board.FindNextColorMoves(this._boardMoved); //найти все возможные ходы из этой доски int Length = this.MovesAvailable.Length; //количество ходов из этого узла if (Length == 0) //если ходов не найдено, значит мат, но кому? { if (_depth % 2 == 0) //нам мат или пат, энивей, проморгали проигрыш/ничью { //нужно предыдущий ход противника пометить как неизбежно ведущий к мату и удалить всех его потомков //потому что если у противника есть возможность поставить нам мат, он ей воспользуется a._valueMin = -1000000;//типа минус бесконечность, потом поменяю если что a._children = null; } else //мы поставили мат { bool CheckCheck = Board.CheckCheck(this._boardMoved, this._boardMoved.NextColor);//проверим ход на шах if (CheckCheck) //если это правда мат { if (_depth == 1) //есть доступный мат в один ход, ничего считать больше не нужно { a._move = this._move; Three._moveFound = true; a._children = null; return;//ничего считать больше не нужно } else//у нас есть доступный мат после вражеского хода. нужно просто пометить ход как потенциально выигрышный { a._valueMax = 1000000; //типа бесконечность, потом поменяю если что //противник знает что этот ход приведет к нашей победе a._children = null; } } else//если это просто пат { this._valueMin = -10000;//стоимость пата, но мы его не хотим, мы хотим раздавить противника. Кожанные мешки...биип.. } } } else //доступные ходы есть теперь нужно узнать, достаточно ли мы глубоко чтобы начать оценивать состояние досок { if (this._depth < _maxDepth - 1)//если мы еще не достигли нужной глубины нужно найти все возможные ходы этой доски { this.Children = new Three[Length]; for (int i = 0; i < Length; i++) { this.Children[i] = new Three(this, i);//он может обнулить массив children в родительском объекте if (this.Children == null) { break; } } this.Children = null; } else//мы достигли нужной глубины //узел в котором мы находимся имеет глубину на единицу меньше максимальной глубины { //мы лишь оценим состояние всех возможных ходов и скажем на что можно рассчитывать родительскому узлу Board TempBoard; int value; //для того чтоб хранить мгновенное состояние доски в цикле: for (int i = 0; i < Length; i++) //нужно оценить состояние всех ходов { TempBoard = Board.DoMove(this._boardMoved, this._movesAvailable[i]); value = AI.Evaluate(this._boardMoved); //оценка состояния доски if ((this._depth + 1) % 2 == 0) //в цикле считаются ходы противника { if (this._valueMin > value) //найти минимальный ход который противник может совершить после моего хода { this._valueMin = value; if (this._parent._valueMax > value) { break; } //альфабета отсечение } } else //в цикле считаются наши ходы { if (this._valueMax < value)//найти максимальный ход который я могу совершить после хода противника { this._valueMax = value; if (this._parent._valueMin < value) { break; } //альфабета отсечение } } } if ((this._depth + 1) % 2 == 0)//альфабета отсечение больших веток { if (a._parent._valueMin < this._valueMin) { this._parent._children = null; } //альфабета отсечение } else { if (a._parent._valueMax > this._valueMax) { this._parent._children = null; } //альфабета отсечение } } } if ((this._depth + 1) % 2 == 0) //теперь нужно передать значение выше { if (a._valueMax < this._valueMin) //найти минимальный ход который противник может совершить после моего хода { a._valueMax = this._valueMin; if (this._depth > 1) { a._parent.UpdateValue(this._valueMin); } } } else { if (a._valueMin > this._valueMax)//найти максимальный ход который я могу совершить после хода противника { a._valueMin = this._valueMax; if (this._depth > 1) { a._parent.UpdateValue(this._valueMax); } } } }