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; } }
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; } }