麻将算法(五)胡牌之M选N

讨论胡牌之前先假设有一幅可以胡牌的牌
一万、一万、二万、二万、二万、三万、三万、三万、四万、四万、四万、七条、八条、九条;
判断这一副牌是胡牌不难,但是想判断可以胡的方式就要用到一种排列组合算法——“M选N”:
把手牌以“同牌”和“连牌”的形式保存到list里,找出一共可以存放的若干种方式,最终选择出来的方式的数量和牌值一


定等于原来手中牌的数量和手中牌的牌值,从M种方式中选择N种方式,这“N”种方式就是可以胡牌的几种方式。
M选N的大致思路是:
(一)m:一共有多少个方式用0表示;
(二)n:一共要选择多少个方式用1表示;
(三)将m、n进行初始化操作;
(四)然后从左到右扫描数组元素值的“10”组合,找到第一个“10”组合后将其变为“01”组合
(五)同时将其左边的所有“1”全部移动到数组的最左端;
(六)当n个“1”全部移动到最右端时,就已经选择完毕;
如下图所示:
  1   1   1   0   0   //1,2,3     
  1   1   0   1   0   //1,2,4     
  1   0   1   1   0   //1,3,4     
  0   1   1   1   0   //2,3,4     
  1   1   0   0   1   //1,2,5     
  1   0   1   0   1   //1,3,5     
  0   1   1   0   1   //2,3,5     
  1   0   0   1   1   //1,4,5     
  0   1   0   1   1   //2,4,5     
  0   0   1   1   1   //3,4,5  
思路说完上代码,看着代码再来一次:


     public static void Swap(ref int my, ref int other)  //这是一个变换两个为数字的方法(int 为值类型,想改


变传进来数字的值,使用ref)
        {
            int temp = my;
            my = other;
            other = temp;
        }


     static List<int[]> GetCombineNFromM(int iSelcetCount, int iCount)  //从所有胡牌方式中选出来我们需要的胡


牌方式 iSelcetCount=4-碰的次数(还需要胡牌的方式),iCount=一共多少种
      {
            List<int[]> comnbineList = new List<int[]>();   //组合种类的集合
            comnbineList.Clear();
            if (iCount < iSelcetCount)   
            {
                return comnbineList;
            }
            else
            {
                int[] comnbine = new int[iCount];
                for (int i = 0; i < iSelcetCount; ++i)  //将数组前n个元素置1,表示第一个组合为前n个数
                {
                    comnbine[i] = 1;
                }
                comnbineList.Add((int[])comnbine.Clone());
                for (int i = 0; i < iCount - 1; ++i)
                {
                    if (comnbine[i] == 1 && comnbine[i + 1] == 0) // 然后从左到右扫描数组元素值的“10”组合


,找到第一个“10”
                    {


                        Swap(ref comnbine[i], ref comnbine[i + 1]);//组合后将其变为“01”组合   
                     
                        int sum = 0;
                        for (int j = 0; j < i; j++)   //统计1的个数
                        {
                            if (comnbine[j] == 1)
                                sum++;
                        }
                        for (int j = 0; j < i; j++)  //移位(将i左边的1全部移动到最左端)
                        {
                            if (j < sum)
                                comnbine[j] = 1;
                            else
                                comnbine[j] = 0;
                        }
                      
                        comnbineList.Add((int[])comnbine.Clone());
                        i = -1;
                    }
                }
            }
            return comnbineList;
        }
下一章:判断“连牌”和“同牌”等方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值