Esempio n. 1
0
        public List <SlotCardsEvalInfo> Evaluation(CardFace[] cardFaces, CardFace[] laizi = null)
        {
            List <SlotCardsEvalInfo> slotCardsEvalGroup = new List <SlotCardsEvalInfo>();

            List <CardFace>[] evalDatas = new List <CardFace>[3]
            {
                new List <CardFace>(),
                new List <CardFace>(),
                new List <CardFace>(),
            };

            CardsTypeInfo?[] cardsTypeInfos = new CardsTypeInfo?[3];

            EvalFuncParamDatas paramDatas = new EvalFuncParamDatas()
            {
                cardFaces            = cardFaces,
                curtSlotCardTypeInfo = null,
                slotCardsEvalGroup   = slotCardsEvalGroup,
                evalDatas            = evalDatas,
                cardsTypeInfos       = cardsTypeInfos,
                slotDepth            = -1,
                refLaizi             = laizi
            };

            CreateEvalInfo(paramDatas);


            //
            slotCardsEvalGroup.Sort(new Comparer2());

            return(slotCardsEvalGroup);
        }
        /// <summary>
        /// 手牌估值
        /// </summary>
        /// <param name="cardFaces"></param>
        /// <param name="laizi"></param>
        /// <returns></returns>
        public List <SlotCardsEvalInfo> Evaluation(CardFace[] cardFaces)
        {
            //排序
            int laiziCount = 0;

            CardInfo[] cardInfos = CardsTransform.Instance.CreateFormatCards(cardFaces, null, ref laiziCount);
            cardFaces = CardsTransform.Instance.CreateCardFaces(cardInfos);

            //
            List <SlotCardsEvalInfo> slotCardsEvalGroup = new List <SlotCardsEvalInfo>();

            List <CardFace>[] evalDatas = new List <CardFace>[3]
            {
                new List <CardFace>(),
                new List <CardFace>(),
                new List <CardFace>(),
            };

            CardsTypeInfo?[] cardsTypeInfos = new CardsTypeInfo?[3];

            EvalFuncParamDatas paramDatas = new EvalFuncParamDatas()
            {
                cardFaces            = cardFaces,
                curtSlotCardTypeInfo = null,
                slotCardsEvalGroup   = slotCardsEvalGroup,
                evalDatas            = evalDatas,
                cardsTypeInfos       = cardsTypeInfos,
                slotDepth            = -1,
            };

            CreateEvalInfo(paramDatas);

            //
            slotCardsEvalGroup.Sort(cardEvalComparer);
            List <SlotCardsEvalInfo> optimalSlotCardsEvalGroup = GetOptimalSlotCardsEvalInfoList(slotCardsEvalGroup);


            return(optimalSlotCardsEvalGroup);
        }
        void CreateEvalInfo(EvalFuncParamDatas paramDatas)
        {
            CardFace[]               cardFaces            = paramDatas.cardFaces;
            CardsTypeInfo?           curtSlotCardTypeInfo = paramDatas.curtSlotCardTypeInfo;
            List <SlotCardsEvalInfo> slotCardsEvalGroup   = paramDatas.slotCardsEvalGroup;

            List <CardFace>[] evalDatas      = paramDatas.evalDatas;
            CardsTypeInfo?[]  cardsTypeInfos = paramDatas.cardsTypeInfos;
            int slotDepth = paramDatas.slotDepth;


            if (curtSlotCardTypeInfo != null)
            {
                //去除当道牌型大于前道牌型的组合
                if (slotDepth >= 1 &&
                    curtSlotCardTypeInfo.Value.type > cardsTypeInfos[slotDepth - 1].Value.type)
                {
                    return;
                }


                //根据赖子牌使用数量,移除当前槽相同数量的赖子牌
                CardFace[] removeLaizi = new CardFace[5];
                if (curtSlotCardTypeInfo.Value.laiziCount > 0)
                {
                    cardFaces = CardsTransform.Instance.RemoveLaiziByCount(
                        cardFaces, laizi, curtSlotCardTypeInfo.Value.laiziCount, removeLaizi);
                }

                //移除当前槽已使用的牌型牌
                CardInfo[] cardInfos = CardsTransform.Instance.CreateRemoveFaceValues(
                    cardFaces, curtSlotCardTypeInfo.Value.cardFaceValues);

                cardFaces = CardsTransform.Instance.CreateCardFaces(cardInfos);

                //添加数据
                evalDatas[slotDepth].AddRange(curtSlotCardTypeInfo.Value.cardFaceValues);
                for (int i = 0; i < curtSlotCardTypeInfo.Value.laiziCount; i++)
                {
                    evalDatas[slotDepth].Add(removeLaizi[i]);
                }

                //
                cardsTypeInfos[slotDepth] = curtSlotCardTypeInfo;
            }

            if (slotDepth == 2)
            {
                int mustSingleCardCount =
                    5 - evalDatas[0].Count +
                    5 - evalDatas[1].Count +
                    3 - evalDatas[2].Count;

                if (cardFaces.Length < mustSingleCardCount)
                {
                    return;
                }

                int   n        = 0;
                int   valueIdx = 0;
                int[] value    = new int[5];

                //尾道
                SlotCardsEvalInfo evalInfo = new SlotCardsEvalInfo();
                evalInfo.slotCardFaceList[0].AddRange(evalDatas[0]);
                for (int i = 0; i < 5 - evalDatas[0].Count; i++)
                {
                    value[valueIdx++] = CardsTransform.Instance.GetValue(cardFaces[n]);
                    if (value[valueIdx - 1] == 1)
                    {
                        value[valueIdx - 1] = 14;
                    }

                    evalInfo.slotCardFaceList[0].Add(cardFaces[n++]);
                }

                if (cardsTypeInfos[0] == null)
                {
                    evalInfo.slotCardsType[0] = CardsType.Single;
                }
                else
                {
                    evalInfo.slotCardsType[0] = cardsTypeInfos[0].Value.type;
                }

                evalInfo.slotScore[0]     = CalCardsScore(cardsTypeInfos[0], null);
                evalInfo.slotShuiScore[0] = GetCardsTypeShuiScore(cardsTypeInfos[0], 0);

                //中道
                valueIdx = 0;
                Array.Clear(value, 0, value.Length);
                evalInfo.slotCardFaceList[1].AddRange(evalDatas[1]);
                for (int i = 0; i < 5 - evalDatas[1].Count; i++)
                {
                    value[valueIdx++] = CardsTransform.Instance.GetValue(cardFaces[n]);
                    if (value[valueIdx - 1] == 1)
                    {
                        value[valueIdx - 1] = 14;
                    }

                    evalInfo.slotCardFaceList[1].Add(cardFaces[n++]);
                }

                if (cardsTypeInfos[1] == null)
                {
                    evalInfo.slotCardsType[1] = CardsType.Single;
                }
                else
                {
                    evalInfo.slotCardsType[1] = cardsTypeInfos[1].Value.type;
                }

                evalInfo.slotScore[1]     = CalCardsScore(cardsTypeInfos[1], null);
                evalInfo.slotShuiScore[1] = GetCardsTypeShuiScore(cardsTypeInfos[1], 1);

                if (evalInfo.slotScore[1] > evalInfo.slotScore[0])
                {
                    return;
                }

                if (evalInfo.slotScore[1] == evalInfo.slotScore[0])
                {
                    int cmp = CmpScoreEqualCards(
                        evalInfo.slotCardFaceList[1].ToArray(), evalInfo.slotCardFaceList[0].ToArray());

                    if (cmp == 1)
                    {
                        return;
                    }
                }

                //头道
                valueIdx = 0;
                Array.Clear(value, 0, value.Length);
                evalInfo.slotCardFaceList[2].AddRange(evalDatas[2]);
                CardFace cf;

                if (3 - evalDatas[2].Count > 0 &&
                    CardsTransform.Instance.GetValue(cardFaces[n]) == 1)
                {
                    int m = newCardFaces.Length - 1;
                    newCardFaces[m--] = cardFaces[n];
                    for (int i = cardFaces.Length - 1; i > n; i--)
                    {
                        newCardFaces[m--] = cardFaces[i];
                    }

                    for (int i = 0; i < 3 - evalDatas[2].Count; i++)
                    {
                        cf = newCardFaces[newCardFaces.Length - i - 1];
                        value[valueIdx++] = CardsTransform.Instance.GetValue(cf);
                        if (value[valueIdx - 1] == 1)
                        {
                            value[valueIdx - 1] = 14;
                        }

                        evalInfo.slotCardFaceList[2].Add(cf);
                    }
                }
                else
                {
                    for (int i = 0; i < 3 - evalDatas[2].Count; i++)
                    {
                        cf = cardFaces[cardFaces.Length - i - 1];
                        value[valueIdx++] = CardsTransform.Instance.GetValue(cf);
                        evalInfo.slotCardFaceList[2].Add(cf);
                    }
                }

                if (cardsTypeInfos[2] == null)
                {
                    evalInfo.slotCardsType[2] = CardsType.Single;
                }
                else
                {
                    evalInfo.slotCardsType[2] = cardsTypeInfos[2].Value.type;
                }

                evalInfo.slotScore[2] = CalCardsScore(cardsTypeInfos[2], null);


                if (evalInfo.slotScore[2] > evalInfo.slotScore[1])
                {
                    return;
                }

                if (evalInfo.slotScore[2] == evalInfo.slotScore[1])
                {
                    int cmp = CmpScoreEqualCards(evalInfo.slotCardFaceList[2].ToArray(), evalInfo.slotCardFaceList[1].ToArray());
                    if (cmp == 1)
                    {
                        return;
                    }
                }

                if (cardsTypeInfos[2] != null && cardsTypeInfos[2].Value.type == CardsType.SanTiao)
                {
                    evalInfo.slotScore[2] += 600;
                }

                evalInfo.slotShuiScore[2] = GetCardsTypeShuiScore(cardsTypeInfos[2], 2);


                //综合估值
                evalInfo.totalScore     = evalInfo.slotScore[0] + evalInfo.slotScore[1] + evalInfo.slotScore[2];
                evalInfo.totalShuiScore = evalInfo.slotShuiScore[0] + evalInfo.slotShuiScore[1] + evalInfo.slotShuiScore[2];

                evalInfo.scoreAndShuiEval =
                    evalInfo.totalScore / maxScore * scoreAndShuiWeight +
                    evalInfo.totalShuiScore / maxShui * (1 - scoreAndShuiWeight);

                //获取三个槽的分值相对总分的偏离方差
                //当总分很高的情况下,如果三个槽的分值相差太大,那么方差会比较高,
                //反之,即三个槽分值相差太不算太大,这时候方差会比较小
                evalInfo.variance = SolveVariance(evalInfo.slotScore);

                //根据偏离程度(方差),取分值的权重,
                //即当偏离值很高时,偏离值对分值的权重影响将会很高,会让分值变的比较低,这种组牌策略为平衡型
                //可以通过调节varianceCubicRange的值来控制影响程度,当varianceCubicRange = 0时,意味着不受
                //偏离程度的影响
                float normalVar = evalInfo.variance / varianceLimit;
                float weight    = 1 - InOutCubic(normalVar, 0f, varianceCubicRange, 1);
                evalInfo.compEval = weight * evalInfo.scoreAndShuiEval;

                //
                slotCardsEvalGroup.Add(evalInfo);

                return;
            }

            //为下一个槽准备数据
            CardsTypeInfo[] info;

            if (slotDepth < 1)
            {
                nextSlotCreater.CreateAllCardsTypeArray(cardFaces);

                if (nextSlotCreater.IsExistNotSingleCardsType())
                {
                    info = nextSlotCreater.GetAllCardsTypeInfo();
                }
                else
                {
                    info = nextSlotCreater.GetAllCardsTypeInfo(false);
                }
            }
            else
            {
                nextSlotCreater.CreateAllCardsTypeArray(cardFaces, 3);
                List <CardsTypeInfo> tmpInfo = new List <CardsTypeInfo>();
                tmpInfo.AddRange(nextSlotCreater.SantiaoList);
                tmpInfo.AddRange(nextSlotCreater.DuiziList);

                int count = Math.Min(5, nextSlotCreater.Single3List.Count);
                for (int i = 0; i < count; i++)
                {
                    tmpInfo.Add(nextSlotCreater.Single3List[i]);
                }

                info = tmpInfo.ToArray();

                if (info.Length == 0)
                {
                    EvalFuncParamDatas paramDatas2 = new EvalFuncParamDatas()
                    {
                        cardFaces            = cardFaces,
                        curtSlotCardTypeInfo = null,
                        slotCardsEvalGroup   = slotCardsEvalGroup,
                        evalDatas            = evalDatas,
                        cardsTypeInfos       = cardsTypeInfos,
                        slotDepth            = slotDepth + 1,
                    };

                    CreateEvalInfo(paramDatas2);
                    evalDatas[slotDepth + 1].Clear();
                    cardsTypeInfos[slotDepth + 1] = null;
                    return;
                }
            }

            //添加一个随机选取后maxCount个牌型数据算法
            int richCount = 0;

            if (slotDepth < 1 && info.Length > maxCount)
            {
                Random rnd = new Random();
                int    n;
                int    maxRandCount = Math.Min(5, info.Length - maxCount);
                richCount = info.Length - maxCount;
                idxs[0]   = -1;

                for (int i = 0; i < maxRandCount; i++)
                {
                    n = rnd.Next(maxCount, info.Length - 1);

                    for (int j = 0; j < i; j++)
                    {
                        if (idxs[j] == n)
                        {
                            n = -1;
                            break;
                        }
                    }

                    idxs[i] = n;
                }

                for (int i = 0; i < maxRandCount; i++)
                {
                    if (idxs[i] == -1)
                    {
                        continue;
                    }

                    EvalFuncParamDatas paramDatas2 = new EvalFuncParamDatas()
                    {
                        cardFaces            = cardFaces,
                        curtSlotCardTypeInfo = info[idxs[i]],
                        slotCardsEvalGroup   = slotCardsEvalGroup,
                        evalDatas            = evalDatas,
                        cardsTypeInfos       = cardsTypeInfos,
                        slotDepth            = slotDepth + 1,
                    };

                    CreateEvalInfo(paramDatas2);
                    evalDatas[slotDepth + 1].Clear();
                    cardsTypeInfos[slotDepth + 1] = null;
                }
            }


            for (int i = 0; i < info.Length - richCount; i++)
            {
                EvalFuncParamDatas paramDatas2 = new EvalFuncParamDatas()
                {
                    cardFaces            = cardFaces,
                    curtSlotCardTypeInfo = info[i],
                    slotCardsEvalGroup   = slotCardsEvalGroup,
                    evalDatas            = evalDatas,
                    cardsTypeInfos       = cardsTypeInfos,
                    slotDepth            = slotDepth + 1,
                };

                CreateEvalInfo(paramDatas2);
                evalDatas[slotDepth + 1].Clear();
                cardsTypeInfos[slotDepth + 1] = null;
            }
        }
Esempio n. 4
0
        void CreateEvalInfo(EvalFuncParamDatas paramDatas)
        {
            CardFace[]               cardFaces            = paramDatas.cardFaces;
            CardsTypeInfo?           curtSlotCardTypeInfo = paramDatas.curtSlotCardTypeInfo;
            List <SlotCardsEvalInfo> slotCardsEvalGroup   = paramDatas.slotCardsEvalGroup;

            List <CardFace>[] evalDatas      = paramDatas.evalDatas;
            CardsTypeInfo?[]  cardsTypeInfos = paramDatas.cardsTypeInfos;
            int slotDepth = paramDatas.slotDepth;

            CardFace[] refLaizi = paramDatas.refLaizi;

            if (curtSlotCardTypeInfo != null)
            {
                //根据赖子牌使用数量,移除当前槽相同数量的赖子牌
                CardFace[] removeLaizi = new CardFace[5];
                cardFaces = CardsTransform.Instance.RemoveLaiziByCount(cardFaces, refLaizi, curtSlotCardTypeInfo.Value.laiziCount, removeLaizi);

                //移除当前槽已使用的牌型牌
                CardInfo[] cardInfos = CardsTransform.Instance.CreateRemoveFaceValues(cardFaces, curtSlotCardTypeInfo.Value.cardFaceValues);
                cardFaces = CardsTransform.Instance.CreateCardFaces(cardInfos);

                //添加数据
                evalDatas[slotDepth].AddRange(curtSlotCardTypeInfo.Value.cardFaceValues);
                evalDatas[slotDepth].AddRange(removeLaizi);
                cardsTypeInfos[slotDepth] = curtSlotCardTypeInfo;
            }

            if (slotDepth == 2)
            {
                int mustSingleCardCount = 5 - evalDatas[0].Count + 5 - evalDatas[1].Count + 3 - evalDatas[2].Count;
                if (cardFaces.Length < mustSingleCardCount)
                {
                    return;
                }

                int   n        = 0;
                int   valueIdx = 0;
                int[] value    = new int[5];

                //尾槽
                SlotCardsEvalInfo evalInfo = new SlotCardsEvalInfo();
                evalInfo.slotCardFaceList[0].AddRange(evalDatas[0]);
                for (int i = 0; i < 5 - evalDatas[0].Count; i++)
                {
                    value[valueIdx++] = CardsTransform.Instance.GetValue(cardFaces[n]);
                    evalInfo.slotCardFaceList[0].Add(cardFaces[n++]);
                }
                evalInfo.slotEval[0] = CalCardsScore(cardsTypeInfos[0].Value, value);


                //中槽
                valueIdx = 0;
                Array.Clear(value, 0, value.Length);
                evalInfo.slotCardFaceList[1].AddRange(evalDatas[1]);
                for (int i = 0; i < 5 - evalDatas[1].Count; i++)
                {
                    value[valueIdx++] = CardsTransform.Instance.GetValue(cardFaces[n]);
                    evalInfo.slotCardFaceList[1].Add(cardFaces[n++]);
                }
                evalInfo.slotEval[1] = CalCardsScore(cardsTypeInfos[1].Value, value);


                //头槽
                valueIdx = 0;
                Array.Clear(value, 0, value.Length);
                evalInfo.slotCardFaceList[2].AddRange(evalDatas[2]);
                for (int i = 0; i < 3 - evalDatas[2].Count; i++)
                {
                    value[valueIdx++] = CardsTransform.Instance.GetValue(cardFaces[n]);
                    evalInfo.slotCardFaceList[2].Add(cardFaces[n++]);
                }
                evalInfo.slotEval[2] = CalCardsScore(cardsTypeInfos[2].Value, value);

                //
                evalInfo.totalEval = evalInfo.slotEval[0] + evalInfo.slotEval[1] + evalInfo.slotEval[2];

                slotCardsEvalGroup.Add(evalInfo);
                return;
            }

            //为下一个槽准备数据
            CardsTypeCreater nextSlotCreater = new CardsTypeCreater();

            nextSlotCreater.CreateAllCardsTypeArray(cardFaces, refLaizi);

            CardsTypeInfo[] info;
            if (nextSlotCreater.IsExistNotSingleCardsType())
            {
                info = nextSlotCreater.GetAllCardsTypeInfo();
            }
            else
            {
                info = nextSlotCreater.GetAllCardsTypeInfo(false);
            }

            for (int i = 0; i < info.Length; i++)
            {
                EvalFuncParamDatas paramDatas2 = new EvalFuncParamDatas()
                {
                    cardFaces            = cardFaces,
                    curtSlotCardTypeInfo = info[i],
                    slotCardsEvalGroup   = slotCardsEvalGroup,
                    evalDatas            = evalDatas,
                    cardsTypeInfos       = cardsTypeInfos,
                    slotDepth            = slotDepth + 1,
                    refLaizi             = refLaizi
                };

                CreateEvalInfo(paramDatas2);
                evalDatas[slotDepth + 1].Clear();
                cardsTypeInfos[slotDepth + 1] = null;
            }
        }