Beispiel #1
0
        /// <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);
                    }
                }
            }
        }