Tic A Tac Poker是泰坦尼克号赌船里的一个游戏,给定9张牌,按照上图的形式排列,牌的位置可以随意调整,要求组合出给定的几手牌。怎么样算一手牌呢,规则如下
三张牌组合符合以下任意情形的,可以作为一手
顺子,同花,两对或者三条,上图中,绿色的线条可以表示可以作为一手的牌,可以看到,总共8组牌中,总共有5手牌
怎么计算呢?直观的思维就是先列出每一种排列,然后对每一种排列进行计算,输出手数最多的那个组合。想法粗糙了一些,有没有更简单的办法呢,应该有,但是我还没有想到,所以,只能用傻一些的办法。
在24点中,用过一种全排列的算法,那种效率相对要低下一些,这里用另外一种全排列算法。它也采用递归,但并不像前面算法需要记录那些数字可选,哪些不可选。它的基本思想是对于一个需要全排列的数组q[],从q[0]开始,按顺序选择一个数字和q[0]交换,然后以q[1]作为数组开头,按照上述的逻辑进行递归,直到程序结束。
得到排列后,将8组牌型进行计算,得出几手,统计出最大的手数和对应的排列,最后输出取得的结果
程序清单
#include <stdio.h>
#include <string.h>
#define END_DATA 10
struct poker
{
int cards_type;//0-3 黑桃,红心,草,方片
int cards_num; //1-13 A-K
};
struct poker input[9] = {
{0,6},
{3,4},
{1,5},
{0,9},
{2,12},
{1,9},
{0,8},
{3,7},
{1,8}
};
int array[10] = {0,1,2,3,4,5,6,7,8,END_DATA};
char card_type[4] = {6,3,5,4};//
char *card_num[] = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
int max_hands_array[9];
int max_hands_count = 0;
// 0 -- 1 -- 2
// | \ | / |
// 3 -- 4 -- 5
// | / | \ |
// 6 -- 7 -- 8
//将8组牌对应的牌以其序号标出
int hand[8][3] = {
{0,1,2},
{3,4,5},
{6,7,8},
{0,3,6},
{1,4,7},
{2,5,8},
{0,4,8},
{2,4,6}
};
void print_poker(struct poker p)
{
printf("%c",card_type[p.cards_type]);
printf("%s",card_num[p.cards_num-1]);
}
void print_card_array(int *array)
{
int i;
for(i=0;i<9;i++)
{
if(i%3==0) printf("\n");
print_poker(input[array[i]]);
}
printf("\n");
}
int ishands(struct poker a,struct poker b,struct poker c)
{
int n;
if(a.cards_num==b.cards_num||b.cards_num==c.cards_num||a.cards_num==c.cards_num) return 0; //pair
if(a.cards_type==b.cards_type&&a.cards_type==c.cards_type) return 0;//flush
n = (a.cards_num-c.cards_num)*(b.cards_num-c.cards_num);
if(n==2||n==-1) //顺子
{
return 0;
}
return -1;
}
void process_hands(int *q)
{
int i,hands=0;
int a,b,c;
for(i=0;i<8;i++)
{
a = q[hand[i][0]];
b = q[hand[i][1]];
c = q[hand[i][2]];
if(ishands(input[a],input[b],input[c])==0) hands++;
}
if(max_hands_count<hands)
{
memcpy(max_hands_array,array,sizeof(max_hands_array));
max_hands_count = hands;
}
}
void get_one_permutation(int *q)
{
int i,j; //i,j是代码界的小明
if(q[0]==END_DATA)
{
process_hands(array);
return;
}
for(i=0;q[i]!=END_DATA;i++)
{
j = q[0];
q[0] = q[i];
q[i] = j;
get_one_permutation(q+1);
q[i] = q[0];
q[0] = j;
}
}
void main()
{
get_one_permutation(array);
print_card_array(max_hands_array);
printf("最大手数%d \n",max_hands_count);
}
输出结果
下节预告
麻将有关