讨论胡牌之前先假设有一幅可以胡牌的牌
一万、一万、二万、二万、二万、三万、三万、三万、四万、四万、四万、七条、八条、九条;
判断这一副牌是胡牌不难,但是想判断可以胡的方式就要用到一种排列组合算法——“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;
}
下一章:判断“连牌”和“同牌”等方法
一万、一万、二万、二万、二万、三万、三万、三万、四万、四万、四万、七条、八条、九条;
判断这一副牌是胡牌不难,但是想判断可以胡的方式就要用到一种排列组合算法——“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;
}
下一章:判断“连牌”和“同牌”等方法