Programming Challenges 习题 2.8.2

本文详细解析了一种扑克牌游戏的算法实现,通过定义扑克牌的结构和类型,使用枚举和结构体来组织牌面信息,实现了对手牌类型的识别和比较。文章深入探讨了从顺子到同花顺的各种牌型的判断逻辑,并通过比较不同类型的手牌来确定胜负。

PC/UVa:110202/10315

Poker Hands

这道题根据题目中的描述的大小,把每一手牌的类型都记录下来,然后再比较就好了,因为只有5张牌,有些就硬编码了,如果像打升级一下子能甩一大堆该怎么判断大小还真不知道。

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>

using namespace std;

enum class Suit
{
	C,D,H,S
};

typedef struct Card
{
	int num;
	Suit suit;
}Card;

enum class Type
{
	HIGHCARD,//最大牌
	PAIR,//一对
	TWOPAIR,//两对
	THREEKIND,//三张相同,
	STRAIGHT,//顺子
	FLUSH,//同花
	FULLHOUSE,//三张相同加一对
	FOURKIND,//四张相同
	STRAIGHTFLUSH,//同花顺
};

typedef struct Rank
{
	Type type;
	union
	{
		int begin;//顺子的最小牌
		int four;//四张相同的点数
		int three;//三张相同的点数
		union
		{
			struct
			{
				char pair1;
				char pair2;
				char other;
			}two;
		}two;
		union
		{
			struct
			{
				char pair;
				char o1, o2, o3;
			}one;
		}one;
	}rank;
}Rank;

istream& operator>>(istream& is, Card& card)
{
	string strCard;
	is >> strCard;
	char chNum = strCard[0], chSuit = strCard[1];
	if (chNum >= '2' && chNum <= '9') card.num = chNum - '0';
	else if (chNum == 'T') card.num = 10;
	else if (chNum == 'J') card.num = 11;
	else if (chNum == 'Q') card.num = 12;
	else if (chNum == 'K') card.num = 13;
	else if (chNum == 'A') card.num = 14;
	if (chSuit == 'C') card.suit = Suit::C;
	else if (chSuit == 'D') card.suit = Suit::D;
	else if (chSuit == 'H') card.suit = Suit::H;
	else if (chSuit == 'S') card.suit = Suit::S;
	return is;
}

bool operator<(const Card &card1, const Card &card2)
{
	if (card1.num < card2.num) return true;
	else return false;
}

Rank getRank(const vector<Card> &vc)
{
	Rank rank;
	rank.type = Type::HIGHCARD;
	rank.rank.begin = vc[0].num;
	//判断顺子和花色
	bool bFlush = true, bStraight = true;
	for (size_t i = 1; i < vc.size(); i++)
	{
		if (vc[i].suit != vc[i - 1].suit){
			bFlush = false;
			break;
		}
	}
	for (size_t i = 1; i < vc.size(); i++)
	{
		if (vc[i].num != vc[i - 1].num + 1){
			bStraight = false;
			break;
		}
	}
	if (bFlush && bStraight){
		rank.type = Type::STRAIGHTFLUSH;
		rank.rank.begin = vc[0].num;
		return rank;
	}
	else if (bFlush){
		rank.type = Type::FLUSH;
		return rank;
	}
	else if (bStraight){
		rank.type = Type::STRAIGHT;
		rank.rank.begin = vc[0].num;
		return rank;
	}
	//判断是否有连续的4张
	if (vc[0].num == vc[1].num && vc[1].num == vc[2].num && vc[2].num == vc[3].num){
		rank.type = Type::FOURKIND;
		rank.rank.four = vc[1].num;
		return rank;
	}
	if (vc[1].num == vc[2].num && vc[2].num == vc[3].num && vc[3].num == vc[4].num){
		rank.type = Type::FOURKIND;
		rank.rank.four = vc[1].num;
		return rank;
	}
	//判断是否有连续的3张,并记下起始位置
	size_t pos = vc.size();
	for (size_t i = 0; i < vc.size() - 2; i++)
	{
		if (vc[i].num == vc[i + 1].num && vc[i + 1].num == vc[i + 2].num){
			pos = i;
			break;
		}
	}
	if (pos == 0){
		rank.rank.three = vc[pos].num;
		if (vc[3].num == vc[4].num) rank.type = Type::FULLHOUSE;
		else rank.type = Type::THREEKIND;
		return rank;
	}
	else if (pos == 1){
		rank.type = Type::THREEKIND;
		rank.rank.three = vc[pos].num;
		return rank;
	}
	else if (pos == 2){
		rank.rank.three = vc[pos].num;
		if (vc[0].num == vc[1].num) rank.type = Type::FULLHOUSE;
		else rank.type = Type::THREEKIND;
		return rank;
	}
	//判断是否有连续的2张,并记下数目和位置
	size_t pair = 0;
	vector<size_t> vsPair, vsSingle;
	for (size_t i = 0; i < vc.size(); i++)
	{
		if (i + 1 < vc.size() && vc[i].num == vc[i + 1].num){
			vsPair.push_back(i);
			pair++;
			i++;
		}
		else vsSingle.push_back(i);
	}
	if (pair == 2){
		rank.type = Type::TWOPAIR;
		rank.rank.two.two.pair1 = (char)vc[vsPair[0]].num;
		rank.rank.two.two.pair2 = (char)vc[vsPair[1]].num;
		rank.rank.two.two.other = (char)vc[vsSingle[0]].num;
		return rank;
	}
	else if (pair == 1){
		rank.type = Type::PAIR;
		rank.rank.one.one.pair = (char)vc[vsPair[0]].num;
		rank.rank.one.one.o1 = (char)vc[vsSingle[0]].num;
		rank.rank.one.one.o2 = (char)vc[vsSingle[1]].num;
		rank.rank.one.one.o3 = (char)vc[vsSingle[2]].num;
		return rank;
	}
	else return rank;
}

int compare(const vector<Card> &vcA, const vector<Card> &vcB)
{
	/*
	-1表示白方胜
	0表示平局
	1表示黑方胜
	*/
	Rank rankA = getRank(vcA), rankB = getRank(vcB);
	if (rankA.type == rankB.type){
		switch (rankA.type)
		{
		case Type::STRAIGHTFLUSH:
		case Type::STRAIGHT:
			if (rankA.rank.begin < rankB.rank.begin) return -1;
			else if (rankA.rank.begin == rankB.rank.begin) return 0;
			else return 1;
		case Type::FOURKIND:
			if (rankA.rank.four < rankB.rank.four) return -1;
			else return 1;
		case Type::FULLHOUSE:
		case Type::THREEKIND:
			if (rankA.rank.three < rankB.rank.three) return -1;
			else return 1;
		case Type::TWOPAIR:
			if (rankA.rank.two.two.pair2 < rankB.rank.two.two.pair2) return -1;
			else if (rankA.rank.two.two.pair2 > rankB.rank.two.two.pair2) return 1;
			else{
				if (rankA.rank.two.two.pair1 < rankB.rank.two.two.pair1) return -1;
				else if (rankA.rank.two.two.pair1 > rankB.rank.two.two.pair1) return 1;
				else{
					if (rankA.rank.two.two.other < rankB.rank.two.two.other) return -1;
					else if (rankA.rank.two.two.other > rankB.rank.two.two.other) return 1;
					else return 0;
				}
			}
		case Type::PAIR:
			if (rankA.rank.one.one.pair < rankB.rank.one.one.pair) return -1;
			else if (rankA.rank.one.one.pair > rankB.rank.one.one.pair) return 1;
			else{
				if (rankA.rank.one.one.o3 < rankB.rank.one.one.o3) return -1;
				else if (rankA.rank.one.one.o3 > rankB.rank.one.one.o3) return 1;
				else{
					if (rankA.rank.one.one.o2 < rankB.rank.one.one.o2) return -1;
					else if (rankA.rank.one.one.o2 > rankB.rank.one.one.o2) return 1;
					else{
						if (rankA.rank.one.one.o1 < rankB.rank.one.one.o1) return -1;
						else if (rankA.rank.one.one.o1 > rankB.rank.one.one.o1) return 1;
						else{
							return 0;
						}
					}
				}
			}
		case Type::FLUSH:
		case Type::HIGHCARD:
			for (size_t i = vcA.size(); i > 0; i--)
			{
				if (vcA[i - 1].num < vcB[i - 1].num) return -1;
				else if (vcA[i - 1].num > vcB[i - 1].num) return 1;
			}
			return 0;
		default:
			return 0;
		}
	}
	else if (rankA.type < rankB.type) return - 1;
	else return 1;
}

int main()
{
	string strLine;
	while (getline(cin, strLine)){
		istringstream iss(strLine);
		vector<Card> vcA, vcB;
		Card card;
		for (int i = 0; i < 5; i++)
		{
			iss >> card;
			vcA.push_back(card);
		}
		sort(vcA.begin(), vcA.end());
		for (int i = 0; i < 5; i++)
		{
			iss >> card;
			vcB.push_back(card);
		}
		sort(vcB.begin(), vcB.end());
		int iRet = compare(vcA, vcB);
		if (iRet == -1) cout << "White wins." << endl;
		else if (iRet == 0) cout << "Tie." << endl;
		else if (iRet == 1) cout << "Black wins." << endl;
	}
	return 0;
}
/*
2H 3D 5S 9C KD 2C 3H 4S 8C AH
2H 4S 4C 2D 4H 2S 8S AS QS 3S
2H 3D 5S 9C KD 2C 3H 4S 8C KH
2H 3D 5S 9C KD 2D 3H 5C 9S KH
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值