Ejemplo n.º 1
0
        /// <summary>
        /// 创建一棵博弈树
        /// </summary>
        /// <param name="RootNode">待生成树的根节点</param>
        /// <param name="ChessBoard_Init">初始棋盘状态</param>
        /// <param name="DepthMax_Set">博弈树深度</param>
        /// <param name="IfShowDebugLog">是否显示调试日志,默认不显示</param>
        public static void CreateGameTree(EnumNowPlayer PolicyPlayer, GameTreeNode RootNode, ChessBoard ChessBoard_Init, int DepthMax_Set, bool IfShowDebugLog = false)
        {
            try
            {
                Exception E = new Exception("最大深度设定错误!请设置为偶数!");
                if (DepthMax_Set % 2 != 0)//必须是偶数
                {
                    throw E;
                }
            }
            catch (Exception e)
            {
                throw;
            }
            DepthMax = DepthMax_Set - 1;
            RootNode.PolicyPlayer = PolicyPlayer;
            if (SearchFrameWork == Enum_GameTreeSearchFrameWork.MinMax)
            {
                RootNode.ExpandNode_MinMax(ChessBoard_Init, RootNode);//3W数量级节点数
                double MaxScore = -1000;
                foreach (GameTreeNode GTN in RootNode.SonNode)
                {
                    if (MaxScore < GTN.score)
                    {
                        MaxScore            = GTN.score;
                        RootNode.NodePlayer = GTN.NodePlayer;
                        RootNode.NodeAction = GTN.NodeAction;
                        RootNode.score      = MaxScore;
                    }
                }
            }
            else
            {
                RootNode.NodeHashCode = GameTreeNode.InitChessBoardHashCode;
                RootNode.ExpandNode_ABPruning(ChessBoard_Init, RootNode, GameTreeNode.IfUseTanslationTable);

                double MaxScore = -1000;
                foreach (GameTreeNode GTN in RootNode.SonNode)
                {
                    if (MaxScore < GTN.beta)
                    {
                        MaxScore              = GTN.beta;
                        RootNode.NodePlayer   = GTN.NodePlayer;
                        RootNode.NodeAction   = GTN.NodeAction;
                        RootNode.score        = MaxScore;
                        RootNode.NodeHashCode = GTN.NodeHashCode;
                    }
                }
                InitChessBoardHashCode = RootNode.NodeHashCode;
            }


            if (IfShowDebugLog)
            {
                PrintGameTree(RootNode);
            }
        }
Ejemplo n.º 2
0
 /// <summary>
 /// 计算博弈树节点总数量,用于测试剪枝性能
 /// </summary>
 /// <param name="NowNode">博弈树根节点</param>
 public static void CalGameTreeNodeNum(GameTreeNode NowNode)
 {
     if (NowNode.SonNode.Count <= 0)
     {
         return;
     }
     foreach (GameTreeNode Son in NowNode.SonNode)
     {
         NodeNum++;
         CalGameTreeNodeNum(Son);
     }
 }
Ejemplo n.º 3
0
        public static int DepthMax = 1000;///博弈树最大深度
        /// <summary>
        /// 以极大极小搜索框架生成博弈树
        /// </summary>
        /// <param name="ThisChessBoard">当前棋盘状态</param>
        /// <param name="ThisNode">当前博弈树节点</param>
        public void ExpandNode_MinMax(ChessBoard ThisChessBoard, GameTreeNode ThisNode)
        {
            ///暂存一些量以便恢复
            EnumNowPlayer PlayerSave = NowQuoridor.ReversePlayer(ThisNode.NodePlayer);

            NowQuoridor.Player_Now = PlayerSave;

            List <QuoridorAction> QABuff = NowQuoridor.ActionList;

            QABuff = NowQuoridor.CreateActionList(ThisChessBoard, GameTreePlayer
                                                  , ThisNode.NodeAction.ActionCheckResult.P1Distance
                                                  , ThisNode.NodeAction.ActionCheckResult.P2Distance);

            foreach (QuoridorAction QA in QABuff)
            {
                #region 保存棋盘状态
                ChessBoard ChessBoardBuff = new ChessBoard();
                ChessBoard.SaveChessBoard(ref ChessBoardBuff, ThisChessBoard);
                #endregion
                #region 模拟落子
                string Hint = NowQuoridor.QuoridorRule.Action(ref ThisChessBoard, QA.ActionPoint.X, QA.ActionPoint.Y, QA.PlayerAction);
                try
                {
                    if (Hint != "OK")
                    {
                        Exception e = new Exception();
                    }
                }
                catch (Exception)
                {
                    throw;
                }
                #endregion

                if (ThisNode.depth <= DepthMax)
                {
                    CreateNewSon(ThisNode, new GameTreeNode(QA
                                                            , PlayerSave, ThisNode.depth + 1, ThisNode.alpha, ThisNode.beta, ThisNode.beta));

                    ExpandNode_MinMax(ThisChessBoard, ThisNode.SonNode.Last());
                }
                else
                {
                    CreateNewSon(ThisNode, new GameTreeNode(QA
                                                            , PlayerSave, ThisNode.depth + 1, QA.WholeScore, QA.WholeScore, QA.WholeScore));
                }
                #region 恢复棋盘状态
                ChessBoard.ResumeChessBoard(ref ThisChessBoard, ChessBoardBuff);
                #endregion
            }
            if (ThisNode.NodePlayer == NowQuoridor.PlayerBuff)//MIN层
            {
                double minvalue = 99999;
                foreach (GameTreeNode Son in ThisNode.SonNode)
                {
                    if (Son.score < minvalue)
                    {
                        minvalue       = Son.score;
                        ThisNode.score = minvalue;
                    }
                }
            }
            else //MAX层
            {
                double maxvalue = -10000;
                foreach (GameTreeNode Son in ThisNode.SonNode)
                {
                    if (Son.score > maxvalue)
                    {
                        maxvalue       = Son.score;
                        ThisNode.score = maxvalue;
                        if (ThisNode.depth == 0)//根节点层
                        {
                            ThisNode.NodeAction = Son.NodeAction;
                            ThisNode.NodePlayer = Son.NodePlayer;
                        }
                    }
                }
            }
        }
Ejemplo n.º 4
0
 /// <summary>
 /// 给该节点添加新的子节点
 /// </summary>
 /// <param name="NewNode">待添加的子节点</param>
 public void CreateNewSon(GameTreeNode FatherNode, GameTreeNode NewNode)
 {
     FatherNode.SonNode.Add(NewNode);
 }
Ejemplo n.º 5
0
        /// <summary>
        /// 获得博弈树节点在TreeView控件上应有的Text属性字符串
        /// </summary>
        /// <param name="NowNode">当前待生成的节点</param>
        /// <param name="IfShowAction">是否显示动作信息</param>
        /// <param name="IfShowActionScore">是否显示动作的评分信息</param>
        /// <returns></returns>
        public static string GetGameTreeNodeViewText(GameTreeNode NowNode, bool IfShowAction = true, bool IfShowActionScore = false)
        {
            string SonTextbuff = "D:";

            SonTextbuff += (NowNode.depth + RootDepth).ToString() + " P";

            switch (NowNode.NodePlayer)
            {
            case EnumNowPlayer.Player1:
                SonTextbuff += "1";
                break;

            case EnumNowPlayer.Player2:
                SonTextbuff += "2";
                break;

            default:
                SonTextbuff += "Error";
                break;
            }
            if (IfShowAction)
            {
                switch (NowNode.NodeAction.PlayerAction)
                {
                case NowAction.Action_PlaceVerticalBoard:
                    SonTextbuff += ((NowNode.NodeAction.ActionPoint.X) * 8 + NowNode.NodeAction.ActionPoint.Y + 1).ToString() + "点和" +
                                   ((NowNode.NodeAction.ActionPoint.X + 1) * 8 + NowNode.NodeAction.ActionPoint.Y + 1).ToString() + "点;";
                    break;

                case NowAction.Action_PlaceHorizontalBoard:
                    SonTextbuff += ((NowNode.NodeAction.ActionPoint.X) * 8 + NowNode.NodeAction.ActionPoint.Y + 1).ToString() + "点和" +
                                   ((NowNode.NodeAction.ActionPoint.X) * 8 + NowNode.NodeAction.ActionPoint.Y + 1 + 1).ToString() + "点";
                    break;

                case NowAction.Action_Move_Player1:
                    SonTextbuff += ((NowNode.NodeAction.ActionPoint.X) * 8 + NowNode.NodeAction.ActionPoint.Y + 1).ToString() + "点";
                    break;

                case NowAction.Action_Move_Player2:
                    SonTextbuff += ((NowNode.NodeAction.ActionPoint.X) * 8 + NowNode.NodeAction.ActionPoint.Y + 1).ToString() + "点";
                    break;

                case NowAction.Action_Wait:
                    SonTextbuff += "Error";
                    break;

                default:
                    SonTextbuff += "Error";
                    break;
                }
            }
            SonTextbuff += " A:";
            Int64  Score    = Convert.ToInt64(NowNode.alpha * 100.0);
            string ScoreStr = (Convert.ToDouble(Score) / 100.0).ToString();

            SonTextbuff += ScoreStr;
            SonTextbuff += ",B:";
            Score        = Convert.ToInt64(NowNode.beta * 100.0);
            ScoreStr     = (Convert.ToDouble(Score) / 100.0).ToString();
            SonTextbuff += ScoreStr.ToString();
            SonTextbuff += ",S:";
            Score        = Convert.ToInt64(NowNode.score * 100.0);
            ScoreStr     = (Convert.ToDouble(Score) / 100.0).ToString();
            SonTextbuff += ScoreStr;

            if (IfShowActionScore)
            {
                SonTextbuff += " SS:";
                SonTextbuff += NowNode.NodeAction.SelfScore.ToString();
                SonTextbuff += " OS:";
                SonTextbuff += NowNode.NodeAction.OpponentScore.ToString();
                SonTextbuff += " WS:";
                Score        = Convert.ToInt64(NowNode.NodeAction.WholeScore * 100.0);
                ScoreStr     = (Convert.ToDouble(Score) / 100.0).ToString();
                SonTextbuff += ScoreStr.ToString();
            }
            # region 显示该动作评分
            # endregion
            if (GameTreeNode.IfUseTanslationTable)
Ejemplo n.º 6
0
        /// <summary>
        /// 以Alpha-Beta剪枝框架并使用TranslationTable生成博弈树
        /// </summary>
        /// <param name="ThisChessBoard">当前棋盘状态</param>
        /// <param name="ThisNode">当前博弈树节点</param>
        public void ExpandNode_ABPruning(ChessBoard ThisChessBoard, GameTreeNode ThisNode, bool IfUseTT = true)
        {
            if (IfUseTT)
            {
                bool IfInTT = false;
                TranslationTable.GameTreeNodeForHash HashNode1 = new TranslationTable.GameTreeNodeForHash();
                HashNode1 = NodeTranslationTable.Search(ThisNode.NodeHashCode, ref IfInTT);
                if (ThisNode.depth != 0 && IfInTT && ThisNode.depth + RootDepth <= HashNode1.depth)
                {
                    ThisNode.alpha = HashNode1.alpha;
                    ThisNode.beta  = HashNode1.beta;
                    return;
                }
            }
            ///暂存一些量以便恢复
            EnumNowPlayer PlayerSave = NowQuoridor.ReversePlayer(ThisNode.NodePlayer);

            NowQuoridor.Player_Now = PlayerSave;

            List <QuoridorAction> QABuff = NowQuoridor.ActionList;

            //QABuff = NowQuoridor.CreateActionList_ALL(ThisChessBoard, ThisNode.P1Distance, ThisNode.P2Distance);
            QABuff = NowQuoridor.CreateActionList(ThisChessBoard, GameTreePlayer
                                                  , ThisNode.NodeAction.ActionCheckResult.P1Distance
                                                  , ThisNode.NodeAction.ActionCheckResult.P2Distance);

            foreach (QuoridorAction QA in QABuff)
            {
                #region 保存棋盘状态
                ChessBoard ChessBoardBuff = new ChessBoard();
                ChessBoard.SaveChessBoard(ref ChessBoardBuff, ThisChessBoard);
                #endregion
                #region 模拟落子
                string Hint = NowQuoridor.QuoridorRule.Action(ref ThisChessBoard, QA.ActionPoint.X, QA.ActionPoint.Y, QA.PlayerAction);
                try
                {
                    if (Hint != "OK")
                    {
                        Exception e = new Exception();
                    }
                }
                catch (Exception)
                {
                    throw;
                }
                if (QA.PlayerAction == NowAction.Action_PlaceHorizontalBoard || QA.PlayerAction == NowAction.Action_PlaceVerticalBoard)
                {
                    if (PlayerSave == EnumNowPlayer.Player1)
                    {
                        ThisChessBoard.NumPlayer1Board -= 2;
                    }
                    else
                    {
                        ThisChessBoard.NumPlayer2Board -= 2;
                    }
                }
                #endregion

                if (ThisNode.depth <= DepthMax)
                {
                    CreateNewSon(ThisNode, new GameTreeNode(QA
                                                            , PlayerSave, ThisNode.depth + 1, ThisNode.alpha, ThisNode.beta, ThisNode.score));

                    if (IfUseTT)
                    {
                        long HashCodeBuff = NodeTranslationTable.NodeGetHashCode(ThisNode.NodeHashCode, QA, ChessBoardBuff);//ThisChessBoard已变,不能作为原棋盘传入,只能上一步的棋盘ChessBoardBuff
                        ThisNode.SonNode.Last().NodeHashCode = HashCodeBuff;
                    }
                    ExpandNode_ABPruning(ThisChessBoard, ThisNode.SonNode.Last(), IfUseTT);
                }
                else
                {
                    CreateNewSon(ThisNode, new GameTreeNode(QA
                                                            , PlayerSave, ThisNode.depth + 1, ThisNode.alpha, QA.WholeScore, QA.WholeScore));
                }

                ChessBoard.ResumeChessBoard(ref ThisChessBoard, ChessBoardBuff);

                #region Min层
                if (ThisNode.NodePlayer == PolicyPlayer)
                {
                    if (ThisNode.SonNode.Last().alpha < ThisNode.beta)
                    {
                        ThisNode.beta  = ThisNode.SonNode.Last().alpha;
                        ThisNode.score = ThisNode.SonNode.Last().alpha;
                    }
                }
                #endregion
                #region Max层
                else
                {
                    if (ThisNode.SonNode.Last().beta > ThisNode.alpha)
                    {
                        ThisNode.alpha = ThisNode.SonNode.Last().beta;
                        ThisNode.score = ThisNode.SonNode.Last().beta;
                    }
                }
                #endregion

                if (ThisNode.depth <= DepthMax && ThisNode.beta <= ThisNode.alpha)//剪枝
                {
                    #region 存入置换表
                    if (IfUseTT)
                    {
                        /*剪枝break前这个时刻该节点已经遍历完毕,可以加入置换表*/
                        TranslationTable.GameTreeNodeForHash HashNodeBuff = new TranslationTable.GameTreeNodeForHash();
                        HashNodeBuff.alpha = ThisNode.alpha;
                        HashNodeBuff.beta  = ThisNode.beta;
                        HashNodeBuff.depth = ThisNode.depth + RootDepth;

                        NodeTranslationTable.Add(ThisNode.NodeHashCode, HashNodeBuff);
                    }
                    #endregion
                    break;
                }
            }
            #region 存入置换表
            if (IfUseTT)
            {
                /*遍历完整个动作列表后可以加入置换表*/
                TranslationTable.GameTreeNodeForHash HashNodeBuff2 = new TranslationTable.GameTreeNodeForHash();
                HashNodeBuff2.alpha = ThisNode.alpha;
                HashNodeBuff2.beta  = ThisNode.beta;
                HashNodeBuff2.depth = ThisNode.depth + RootDepth;

                NodeTranslationTable.Add(ThisNode.NodeHashCode, HashNodeBuff2);
            }
            #endregion
        }