炸金花&四川麻将

炸金花

这周老师布置了一个"很困难的实验",大致的内容如下:
在这里插入图片描述
在这里插入图片描述

我大致翻译一下,就是给定的五种牌,判断这五张牌能够组成的最好的特殊组合。

但是在输入方面需要注意的是,就是输入可能是非法输入(输入的牌不存在),或者是重复输入(重复输入已经输入过的牌),我这里的想法就是预先建立一个映射:

for (int i = 0;i < 4;i++) {
   //首先我们要建立映射
		switch (i){
   //表示牌型名
			case 0:x = "c";break; case 1:x = "d";break;
			case 2:x = "h";break; case 3:x = "s";break;
		}
		for (int j = 0;j < 13;j++) {
   
			string xx;
			switch (j) {
   //牌在某个牌型里的序号
			case 1:xx = "2" + x;break; case 2:xx = "3" + x;break; case 3:xx = "4" + x;break;
			case 4:xx = "5" + x;break; case 5:xx = "6" + x;break; case 6:xx = "7" + x;break;
			case 7:xx = "8" + x;break; case 8:xx = "9" + x;break; case 9:xx = "t" + x;break;
			case 10:xx = "j" + x;break; case 11:xx = "q" + x;break;
			case 12:xx = "k" + x;break; case 13:xx = "a" + x;break;
			}
			card_id[xx] = 1+(13*i+j)*10;//其中1表示是否已经取过这张牌了
		}
	}

这里的1表示是否取过,是为了后面判断是否取过这张牌做铺垫。

接下来是输入:

int i;
	for (i = 0;i <5;) {
   
		cout << "Enter a card:"; cin >> s;
		//如果映射中不存在,肯定就是张坏牌
		if (!card_id.count(s)) {
    cout << "Bad card,ignored.\n";continue; }
		//映射中存在,但是已经取过了,就是非法取牌
		if (card_id[s] % 10 == 0) {
    cout << "Duplicate card,ignored.\n";continue; }
		card_id[s]--; a[i] = card_id[s] / 10;i++;
	}

映射和输入完毕,接下来我们只需要处理判断牌型就可以了,第一种是同花顺,事实上就是顺子和同花的结合。

顺子函数:

bool is_straight(int b,int c,int d,int e,int f) {
   //判断是否为顺子
	//将每张牌的序号除以13的余数表示这张牌在他们牌堆里的序号,如果差值都为1就是顺子了
	int bb = b % 13, cc = c % 13, dd = d % 13, ee = e % 13, ff = f % 13;
	if (cc - bb == 1 && dd - cc == 1 && ee - dd == 1 && ff - ee == 1) return true;
	else return false;
}

同花函数:

bool is_flush(int b, int c, int d, int e, int f){
   //判断是否为同花
	//将每张牌的序号除以13得到值表示处于第几个牌型,五张牌牌型相同即表示为同花顺
	if (b / 13 == c / 13 && c / 13 == d / 13 && d / 13 == e / 13 && e / 13 == f / 13) return true;
	else return false;
}

接下来就是四个头,三个头,对子函数的编译,这三个函数的内核算法本质是类似的。

四个头函数:

bool is_four(int b, int c, int d, int e, int f) {
   //判断是否为炸弹
	int num[20]; memset(num, 0, sizeof(num));//本质是桶排序
	//以牌在他们的牌堆里的序号作为桶的序号,如果有一个桶里的值为4,就表示含有炸弹
	num[b % 13]++; num[c % 13]++; num[d % 13]++; num[e % 13]++; num[f % 13]++;
	for (int i = 0;i < 13;i++) {
   if (num[i] == 4) return true;}
	return false;
}

三个头函数是一样的:

bool is_three(int b, int c, int d, int e, int f) {
   //判断是否有三个头
	int num[20]; memset(num, 0, sizeof(num));//思想上和判断炸弹函数一样的
	num[b % 13]++; num[c % 13]++; num[d % 13]++; num[e % 13]++; num[f % 13]++;
	for (int i = 0;i < 13;i++) {
    if (num[i] == 3) return true; }
	return false;
}

需要注意的是,由于有一种牌型是two_pairs。也就是说pair函数返回的应该是这个牌型里的对子个数:

int pair_num(int b, int c, int d, int e, int f) {
   //对子个数函数
	int num[20],ans=0; memset(num, 0, sizeof(num));//思想本质和前面两个函数是一样的
	num[b % 13]++; num[c % 13]++
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值