【C练习】德州扑克

//读入五张手牌并将牌分类
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_RANK 13 //13种点数
#define MAX_SUIT 4 //4种花色

//牌型从大到小分别是:
//1->皇家同花顺(Royal flush)
//2->同花顺(Straight flush)
//3->四张(Four of a kind)
//4->葫芦(Fullhouse)
//5->同花(Flush)
//6->顺子(Straight)
//7->三张(Three of a kind)
//8->两对(Two pairs)
//9->一对(Pair)
//10->高牌(High card)
enum hand
{
	royal_flush = 1,
	straight_flush,
	four_of_a_kind,
	fullhouse,
	flush,
	straight,
	three_of_a_hand,
	two_pairs,
	pair,
	high_card
};

const int card_nums = 5; //总共5张牌
const char rank[MAX_RANK] = { 'a', '2', '3', '4', '5', '6', '7', '8', '9', 't', 'j', 'q', 'k' };
const char suit[MAX_SUIT] = { 'd', 'c', 'h', 's' }; //diamond, club, heart, spade

int mycard[MAX_RANK + 1][MAX_SUIT] = { 0 }; //我的牌

//发牌
void deal(void);

//判断牌型并返回
enum hand check(void);

//打印牌型
void hand_print(enum hand);

//重置
void reset(void);

int main()
{
	while (1)
	{
		deal();
		hand_print(check());		
		reset();
	}
	return 0;
}

//发牌
void deal(void)
{
	int cnt = card_nums; //剩余牌数
	while (cnt)
	{
		char rr, ss; //点数&花色
		int rr_i = 0, ss_i = 0; //点数&花色对应数组下标

		//以字符形式输入点数和花色,并忽略多余换行
		printf("Enter a card: ");
		while ((rr = getchar()) == '\n')
			;
		if (rr == '0')
		{
			exit(EXIT_SUCCESS);
		}
		while ((ss = getchar()) == '\n')
			;
		
		while (getchar() != '\n')
			;

		for (; rr_i < MAX_RANK && rank[rr_i] != rr; rr_i++)
			;
		for (; ss_i < MAX_SUIT && suit[ss_i] != ss; ss_i++)
			;

		//判断点数和花色是否合法
		if (rr_i == MAX_RANK || ss_i == MAX_SUIT)
		{
			printf("Bad card; ignored.\n");
			continue;
		}

		//判断点数和花色是否重复
		if (mycard[rr_i][ss_i])
		{
			printf("Duplicate card; ignored.\n");
			continue;
		}

		cnt--;
		mycard[rr_i][ss_i] = 1;
		if (rr_i == 0) mycard[MAX_RANK][ss_i] = 1;
	}	
}

//判断牌型并返回
enum hand check(void)
{	
	int rank_cnt[MAX_RANK + 1] = { 0 }; //每种点数的牌有几张,rank_cnt[0] = rank_cnt[13]
	int suit_cnt[MAX_SUIT] = { 0 }; //每种花色的牌有几张
	int max_rank_cnt = 0; //点数相同的牌最多有几张
	int max_suit_cnt = 0; //花色相同的牌最多有几张
	int pair_cnt = 0; //对子数量

	for (int i = 0; i < MAX_RANK; i++)
	{
		for (int j = 0; j < MAX_SUIT; j++)
		{
			if (mycard[i][j])
			{
				rank_cnt[i]++;
				if (i == 0) rank_cnt[MAX_RANK]++;
				max_rank_cnt = rank_cnt[i] > max_rank_cnt ? rank_cnt[i] : max_rank_cnt;

				suit_cnt[j]++;
				max_suit_cnt = suit_cnt[j] > max_suit_cnt ? suit_cnt[j] : max_suit_cnt;
			}
		}
	}

	for (int i = 0; i < MAX_RANK; i++)
	{
		if (rank_cnt[i] == 2)
		{
			pair_cnt++;
		}
	}

	//判断同花顺
	if (max_suit_cnt >= 5)
	{
		int suit_selected = 0;
		for (int i = 0; i < MAX_SUIT; i++)
		{
			if (suit_cnt[i] >= 5)
			{
				suit_selected = i;
				break;
			}
		}
		for (int i = 0; i < MAX_RANK - 3; i++)
		{
			if (mycard[i][suit_selected] && mycard[i + 1][suit_selected] && mycard[i + 2][suit_selected] 
				&& mycard[i + 3][suit_selected] && mycard[i + 4][suit_selected])
			{
				if (i == MAX_RANK - 4) return royal_flush;
				return straight_flush;
			}
		}
	}

	//判断四张
	if (max_rank_cnt == 4) return four_of_a_kind;

	//判断葫芦
	if (max_rank_cnt == 3 && pair_cnt) return fullhouse;

	//判断同花
	if (max_suit_cnt >= 5) return flush;

	//判断顺子
	for (int i = 0; i < MAX_RANK - 3; i++)
	{
		if (rank_cnt[i] && rank_cnt[i + 1] && rank_cnt[i + 2] && rank_cnt[i + 3] && rank_cnt[i + 4])
		{
			return straight;
		}
	}

	//判断三张
	if (max_rank_cnt == 3) return three_of_a_hand;

	//判断两对
	if (pair_cnt >= 2) return two_pairs;

	//判断一对
	if (pair_cnt == 1) return pair;

	//都不是则为高牌
	return high_card;
}

//打印牌型
void hand_print(enum hand h)
{
	char* hand[] =
	{
		"",
		"Royal flush",
		"Straight flush",
		"Four of a kind",
		"Fullhouse",
		"Flush",
		"Straight",
		"Three of a hand",
		"Two pairs",
		"Pair",
		"High card"
	};

	printf("%s\n\n",hand[h]);
}

//重置
void reset(void)
{
	memset(mycard, 0, sizeof(mycard));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值