十三张/十三水

规则介绍: 
https://baike.baidu.com/item/%E5%8D%81%E4%B8%89%E6%B0%B4/81938

十三水规则:
    二到四人对局,,一副牌,除去大王,小王,剩下总共52张牌;游戏中每人获得13张牌;
游戏规则
    每位玩家需将手上的13张牌分成头、中、尾三墩牌,头墩三张,中尾墩各五张。

普通牌型(3、5张牌)
    同花顺:同门花色中之五张连续牌。若别家也有同花顺时,比顺子大小如牌型全部相同,则平局。 在底墩,按5道计;在中墩,则记10道;
    铁支(四条):4张相同的牌。在底墩,按4道计;在中墩,则记8道;
    葫芦:由三条加一对组成。若别家也有此牌型,则比三张数字大小。 放中墩,则计3道;
    同花:同门花色中之五张杂牌。若遇相同则先比这副牌中最大的一支,如又相同再比第二支、依此类推。如牌型全部相同则平局;
    顺子:五张牌都是连续的组合,2、3、4、5、6为最小牌。 10、J、Q、K、A为最大牌,若巧遇别家也有则平局。道:第二大的牌不是9、10、J、Q、K(此为第三大)而是A、2、3、4、5;
    三条:三张相同的牌。若遇相同,则比三条部分的数字大小。 在头墩,以三尖刀计;
    三尖刀:头墩为三条。 按3道计。
    二对:牌型中五张牌由两组两张相同数字的牌所组成。若遇相同则先比这副牌中最大的一对,如又相同再比第二对、如又相同再比单张牌大小。如牌型全部相同则平局。
    对子:由两张相同数字的牌组成。若别家也相同则比剩下牌的数字大小,如牌型全部相同则平局。 第一墩是两张带一张,后面是两张带三张;
    乌龙(散牌):组不出任何牌型。只比数字大小,其比法与同花相同。若两家从大到小都一样,则平局;

后台逻辑实现思路: 
一手牌是13张,要组成头墩、中墩、尾墩,每墩可能分别是同花顺、铁枝……对子、乌龙等,要保证尾墩 >= 中墩 > 头墩。可以通过遍历所有类型,获取指定的尾墩组合后,对剩余的牌再进行组合,优先使用递归。 
伪代码:

// CCombinateCards 组合类
// ST_ONE_HAND_COMBINATION 一手牌组合
// ST_CARD_SENTENCE 一墩牌,三张或五张
typedef std::vector<ST_ONE_HAND_COMBINATION> COneHandArray;

bool CCombinateCards::CombinateSpecifiedStyle(COneHandArray &arrTraverseArray,BYTE byType)
{
    CCombinateCards clsGroup = *this;   
    if (clsGroup.m_nCount == 0)
    {
        return true;
    }

    int iStcTypeCount = 0;
    int iSentence = 0;
    int iPos = clsGroup.m_nCount / MAX_SENTENCE_LENGTH;                 // 头、中、尾
    int iLength = iPos == EN_LOCALTION_HEAD? MIN_SENTENCE_LENGTH : MAX_SENTENCE_LENGTH;
    bool bTail = clsGroup.m_nCount == MAX_CARDS_EVERYONE;

    std::vector<ST_CARD_SENTENCE> arrSentence;
    if (byType >= EN_ST_TONGHUASHUN && m_nCount >= MAX_SENTENCE_LENGTH)
    {
        int iTonghuashunCount = NormalTonghuashun(arrSentence);
        if (byType == EN_ST_TONGHUASHUN && bTail && iTonghuashunCount == 0)
        {
            return false;
        }
        for (;iSentence < iTonghuashunCount;++iSentence)    // 如果有同花顺,则将该顺子从手牌中删除,拼凑头和中
        {
            CCombinateCards clsGroupTmp = clsGroup;
            if (!clsGroupTmp.DeleteSentence(arrSentence[iSentence],iLength))        // 删除该句子,获得剩余的牌
            {
                return false;
            }

            if (bTail)                      // 如果是尾墩,应该新建一个 ST_ONE_HAND_CARD ,如果是中或头,则往 arrTraverseArray 的最后一个 ST_ONE_HAND_CARD 中添加
            {
                ST_ONE_HAND_COMBINATION stOneHand;
                stOneHand.SetLocationCard(EN_LOCALTION_TAIL,arrSentence[iSentence]);
                arrTraverseArray.push_back(stOneHand);
            }
            else
            {
                // 如果是取中墩,且已经有一个中墩了,再新建一个 ST_ONE_HAND_COMBINATION ,尾墩不需要新建。如果是尾墩则直接往 arrTraverseArray 里面设置
                if (iPos == EN_LOCALTION_MID && arrTraverseArray[arrTraverseArray.size() - 1].m_astSentence[EN_LOCALTION_MID].IsValidSentence())
                {
                    ST_ONE_HAND_COMBINATION stOneHand;
                    stOneHand.m_astSentence[EN_LOCALTION_TAIL] = arrTraverseArray[arrTraverseArray.size() - 1].m_astSentence[EN_LOCALTION_TAIL];
                    arrTraverseArray.push_back(stOneHand);
                }
                arrTraverseArray[arrTraverseArray.size() - 1].SetLocationCard(iPos,arrSentence[iSentence]);                 
            }

            clsGroupTmp.CombinateSpecifiedStyle(arrTraverseArray,EN_ST_TONGHUASHUN);                                        // 此处获得的是以同花顺为尾墩的组合
        }

        if (iTonghuashunCount > 0 && bTail)
        {
            return true;
        }
    }


    if (byType >= EN_ST_TIEZHI)
    {
        int iTiezhiCount = NormalTiezhi(arrSentence);                                           // 到这里肯定没有同花顺了,此时从剩余的单牌中找一个放入 arrSentence 中
        if (byType == EN_ST_TIEZHI && bTail && iTiezhiCount == 0)
        {
            return false;
        }

        for (iSentence = 0;iSentence < iTiezhiCount;++iSentence)                                // 如果有铁枝,则将该铁枝从手牌中删除,拼凑头和中
        {
            CCombinateCards clsGroupTmp = clsGroup;
            if (!clsGroupTmp.DeleteSentence(arrSentence[iSentence],arrSentence[iSentence].m_iSentenceLen))      // 删除该句子,获得剩余的牌
            {
                return false;
            }

            if (bTail)                      // 如果是尾墩,应该新建一个 ST_ONE_HAND_CARD ,如果是中或头,则往 arrTraverseArray 的最后一个 ST_ONE_HAND_CARD 中添加
            {
                ST_ONE_HAND_COMBINATION stOneHand;
                stOneHand.SetLocationCard(EN_LOCALTION_TAIL,arrSentence[iSentence]);
                arrTraverseArray.push_back(stOneHand);
            }
            else
            {
                // 如果是取中墩,且已经有一个中墩了,再新建一个 ST_ONE_HAND_COMBINATION ,尾墩不需要新建。如果是尾墩则直接往 arrTraverseArray 里面设置
                if (iPos == EN_LOCALTION_MID && arrTraverseArray[arrTraverseArray.size() - 1].m_astSentence[EN_LOCALTION_MID].IsValidSentence())
                {
                    ST_ONE_HAND_COMBINATION stOneHand;
                    stOneHand.m_astSentence[EN_LOCALTION_TAIL] = arrTraverseArray[arrTraverseArray.size() - 1].m_astSentence[EN_LOCALTION_TAIL];
                    arrTraverseArray.push_back(stOneHand);
                }
                arrTraverseArray[arrTraverseArray.size() - 1].SetLocationCard(iPos,arrSentence[iSentence]);
            }
            clsGroupTmp.CombinateSpecifiedStyle(arrTraverseArray,EN_ST_TIEZHI);                                         // 此处是以铁枝为尾墩的组合
        }
        if (iTiezhiCount > 0  && bTail)
        {
            return true;
        }
    }

        // 中间其他类型省略 ...

    int iWulongCount = NormalWulong(arrSentence);
    //if (byType == EN_ST_WULONG/* && bTail */&& iWulongCount == 0)                             // 乌龙不会出现在尾墩
    //{
    //  return false;
    //}
    for (iSentence = 0;iSentence < iWulongCount;++iSentence)                                    // 如果有葫芦,则将该葫芦从手牌中删除,拼凑头和中
    {
        CCombinateCards clsGroupTmp = clsGroup;
        if (!clsGroupTmp.DeleteSentence(arrSentence[iSentence],iLength))        // 删除该句子,获得剩余的牌
        {
            return false;
        }

        if (bTail)                      // 如果是尾墩,应该新建一个 ST_ONE_HAND_CARD ,如果是中或头,则往 arrTraverseArray 的最后一个 ST_ONE_HAND_CARD 中添加
        {
            ST_ONE_HAND_COMBINATION stOneHand;
            stOneHand.SetLocationCard(EN_LOCALTION_TAIL,arrSentence[iSentence]);
            arrTraverseArray.push_back(stOneHand);
        }
        else
        {
            // 如果是取中墩,且已经有一个中墩了,再新建一个 ST_ONE_HAND_COMBINATION ,尾墩不需要新建。如果是尾墩则直接往 arrTraverseArray 里面设置
            if (iPos == EN_LOCALTION_MID && arrTraverseArray[arrTraverseArray.size() - 1].m_astSentence[EN_LOCALTION_MID].IsValidSentence())
            {
                ST_ONE_HAND_COMBINATION stOneHand;
                stOneHand.m_astSentence[EN_LOCALTION_TAIL] = arrTraverseArray[arrTraverseArray.size() - 1].m_astSentence[EN_LOCALTION_TAIL];
                arrTraverseArray.push_back(stOneHand);
            }
            arrTraverseArray[arrTraverseArray.size() - 1].SetLocationCard(iPos,arrSentence[iSentence]);
        }
        clsGroupTmp.CombinateSpecifiedStyle(arrTraverseArray,EN_ST_WULONG);                                         // 
    }

    return true;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值