Пример #1
0
    //依據棋局狀態找出最高分點(依ScoreMode排序分數高低之後, 再以陣營(type)個別對格子進行評分)
    private List <MaxMinNode> ReturnHighestList(int[,] grid, int type, ScoreMode mode, int amount, int layer, string numberName)
    {
        List <MaxMinNode> nodeList = new List <MaxMinNode>();

        //記錄所有棋盤格的分數
        for (int i = 0; i <= grid.GetUpperBound(1); i++)
        {
            for (int j = 0; j <= grid.GetUpperBound(0); j++)
            {
                if (grid[j, i] == 0)
                {
                    int score = 0;

                    switch (mode)
                    {
                    case ScoreMode.此陣營最高分:
                        score += ScoreChessPoint(new Vector2(j, i), grid, type, false, false);
                        break;

                    case ScoreMode.方最高分:
                        int awayType = type == 1 ? 2 : 1;
                        score += ScoreChessPoint(new Vector2(j, i), grid, awayType, false, false);
                        break;

                    case ScoreMode.雙方合計最高分:
                        score += ScoreChessPoint(new Vector2(j, i), grid, 1, false, false);
                        score += ScoreChessPoint(new Vector2(j, i), grid, 2, false, false);
                        break;
                    }

                    if (score != 0) //只有分數不為0時才會採用至List
                    {
                        if (score > c_maxScore)
                        {
                            score = c_maxScore;                     //設置上限
                        }
                        MaxMinNode _n = new MaxMinNode(score, new Vector2(j, i), layer, numberName);
                        nodeList.Add(_n);
                    }
                }
            }
        }

        //排序
        nodeList.Sort((MaxMinNode x, MaxMinNode y) =>
        {
            if (x.score < y.score)
            {
                return(1);
            }
            if (x.score > y.score)
            {
                return(-1);
            }
            return(0);
        }
                      );

        //只保留amount個最大值
        if (nodeList.Count != 0)
        {
            nodeList.RemoveRange(amount, nodeList.Count - amount);
        }

        //設定編號名稱
        for (int i = 0; i < nodeList.Count; i++)
        {
            nodeList[i].number = nodeList[i].number + i.ToString();
        }

        if (mode != ScoreMode.此陣營最高分) //根據陣營(type)改變node分數(但如果mode為"此陣營最高分", 則無需重複評分)
        {
            for (int i = 0; i < nodeList.Count; i++)
            {
                nodeList[i].score = ScoreChessPoint(new Vector2(nodeList[i].pos.x, nodeList[i].pos.y), grid, type, false, false);
            }
        }

        return(nodeList);
    }
Пример #2
0
    public List <MaxMinNode> BuildNodeList(int[,] grid, int amount, int deep, string numberName, bool assOrAway, MaxMinNode headNode)
    {
        List <MaxMinNode> _nodeList = new List <MaxMinNode>();
        bool breakBranch            = false; //是否斷枝

        if (assOrAway && deep > 0)           //我方回合且深度大於0時(非最後一項), 抓出amount個分數最大值位置
        {
            _nodeList = ReturnHighestList(grid, aiChessType, ScoreMode.雙方合計最高分, amount, deep, numberName);
        }
        else if (assOrAway && deep == 0) //我方回合且深度等於0時(最後一項), 只取最大分數位置
        {
            //_nodeList = ReturnHighestList(grid, aiChessType, ScoreMode.雙方合計最高分, 1, deep, numberName);
            _nodeList = Deduce(grid, aiChessType, deep, numberName);
        }
        else if (!assOrAway) //對方回合時, 使用特殊演算法去預測可能會下的位置
        {
            _nodeList = Deduce(grid, playerType, deep, numberName);

            for (int i = 0; i < _nodeList.Count; i++)
            {
                _nodeList[i].score *= -1;
            }
        }

        //若分數在分數上限值以上時剪枝, 不繼續推演
        for (int i = 0; i < _nodeList.Count; i++)
        {
            if (Mathf.Abs(_nodeList[i].score) >= c_maxScore)
            {
                breakBranch = true;
            }
        }

        for (int i = 0; i < _nodeList.Count; i++) //生成的所有node再往下生成分支
        {
            if (deep > 0)                         //若深度大於0(尚未到最後一項), 則向下生成分枝
            {
                int[,] nextGrid = (int[, ])grid.Clone();
                nextGrid[(int)_nodeList[i].pos.x, (int)_nodeList[i].pos.y] = assOrAway ? aiChessType : playerType; //推演棋盤

                if (!breakBranch)
                {
                    _nodeList[i].childBranch = BuildNodeList(nextGrid, amount, deep - 1, _nodeList[i].number, !assOrAway, _nodeList[i]);
                }
            }

            if (_nodeList[i].nodeAcc.Count == 0)
            {
                _nodeList[i].nodeAcc.Add(_nodeList[i].score);                                  //若累計分數的項目數等於0(最後一項), 則將自己的分數加進累計總分
            }
            else //若累計分數的項目數大於1(前面已有子分枝將分數加上來), 則只要對累計總分再累加自己的分數上去即可
            {
                for (int j = 0; j < _nodeList[i].nodeAcc.Count; j++)
                {
                    _nodeList[i].nodeAcc[j] += _nodeList[i].score;
                    if (_nodeList[i].nodeAcc[j] >= c_maxScore)
                    {
                        _nodeList[i].nodeAcc[j] = c_maxScore;                                        //設置分數上限
                    }
                }
            }

            if (headNode != null) //若上層node不為null, 則將累計總分往母分枝丟, 若項目數為多個(來自不同子分枝的累加總分), 則只挑出最大值
            {
                if (_nodeList[i].nodeAcc.Count > 1)
                {
                    _nodeList[i].nodeAcc.Sort();
                }
                headNode.nodeAcc.Add(_nodeList[i].nodeAcc[_nodeList[i].nodeAcc.Count - 1]);
            }
            else
            {
                _nodeList[i].nodeAcc.Sort();
            }

            //_nodeList[i].TestMessage();
        }

        return(_nodeList);
    }