ZOJ 1111 &PE 54 oker hands(大模拟扑克)

16 篇文章 0 订阅
2 篇文章 0 订阅

A poker deck contains 52 cards - each card has a suit which is one of clubs, diamonds, hearts, or spades (denoted C, D, H, S in the input data). Each card also has a value which is one of 2, 3, 4, 5, 6, 7, 8, 9, 10, jack, queen, king, ace (denoted 2, 3, 4, 5, 6, 7, 8, 9, T, J, Q, K, A). For scoring purposes, the suits are unordered while the values are ordered as given above, with 2 being the lowest and ace the highest value.

A poker hand consists of 5 cards dealt from the deck. Poker hands are ranked by the following partial order from lowest to highest

  • High Card. Hands which do not fit any higher category are ranked by the value of their highest card. If the highest cards have the same value, the hands are ranked by the next highest, and so on.
  • Pair. 2 of the 5 cards in the hand have the same value. Hands which both contain a pair are ranked by the value of the cards forming the pair. If these values are the same, the hands are ranked by the values of the cards not forming the pair, in decreasing order.
  • Two Pairs. The hand contains 2 different pairs. Hands which both contain 2 pairs are ranked by the value of their highest pair. Hands with the same highest pair are ranked by the value of their other pair. If these values are the same the hands are ranked by the value of the remaining card.
  • Three of a Kind. Three of the cards in the hand have the same value. Hands which both contain three of a kind are ranked by the value of the 3 cards.
  • Straight. Hand contains 5 cards with consecutive values. Hands which both contain a straight are ranked by their highest card.
  • Flush. Hand contains 5 cards of the same suit. Hands which are both flushes are ranked using the rules for High Card.
  • Full House. 3 cards of the same value, with the remaining 2 cards forming a pair. Ranked by the value of the 3 cards.
  • Four of a kind. 4 cards with the same value. Ranked by the value of the 4 cards.
  • Straight flush. 5 cards of the same suit with consecutive values. Ranked by the highest card in the hand.
Your job is to compare several pairs of poker hands and to indicate which, if either, has a higher rank.

Input Specification

Several lines, each containing the designation of 10 cards: the first 5 cards are the hand for the player named "Black" and the next 5 cards are the hand for the player named "White."

Output Specification

For each line of input, print a line containing one of:

   Black wins.
   White wins.
   Tie.

Sample Input

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

Sample Output

White wins.
Black wins.
Black wins.
Tie.
题意:这道题要求比较两手牌的大小。每手牌都有5张牌组成,牌的大小的定义如下,首先确定这组牌的所属种类是下面哪一种(若同属同一种类,则根据该分类后面的比较规则继续比较,所属种类越靠后牌越大)。
          ● High Card:杂牌(不属于下面任何一种)。根据牌从大到小的顺序依次比较。
          ● Pair:有一对,加3张杂牌组成。先比较对的大小,再从大到小的顺序比较杂牌。
          ● Two Pairs:有两对,加1帐杂牌。先从大到小比较对的大小,再比较杂牌。
          ● Three of a Kind:有3张值相同的牌。比较这个值即可。
          ● Straingt:一条龙。即5张牌连续。比较最大的一张牌即可。
          ● Flush:清一色。即5张牌花色相同。和杂牌一样比较。
          ● Full House:3张值相同的牌,加上一对。比较三张相同的值即可。
          ● Four of a kind:有4张牌相同,即相当于一副“炸弹”。
          ● Straight flush:同花顺。即5张牌花色相同,并且连续。例如同花色的34567。
          题目输入多行,每一行含有10张牌,前五张属于Black,后五张属于White,每张牌由“牌值”字符和“花色”字符组成,注意10用大写字母T表示。牌从小到大的顺序是2,3,4,5,6,7,8,9,T,J,Q,K,A。要求输出比较结果。
          例如输入:
          2H 3D 5S 9C KD 2C 3H 4S 8C AH   (输出:White wins.)
          2H 4S 4C 2D 4H 2S 8S AS QS 3S   (输出:Black wins.)
          2H 3D 5S 9C KD 2C 3H 4S 8C KH  (输出:Black wins.)
          2H 3D 5S 9C KD 2D 3H 5C 9S KH  (输出:Ties.)
题解:一道比较复杂的模拟题...只需要根据题目要求的比较规则去比较即可,我们假设一副牌所属的种类,用level值表示,level越大则牌越大。使用一个函数 int GetLevel(...) 来获取一副牌所属的种类。这里再判断牌的level之前,由于输入是乱序的,为了判别我们需要先把5张牌按从小到大的顺序排序。如果两幅牌的level相同,则我们还要具体根据牌的点数(value)做进一步判断,因此我们给GetLevel函数再传入一个int数组,把同level的继续比较的指标点数按顺序放入这个数组。这样,当level相同时,我们就继续从头查看order数组里的判别指标来继续判断。这道题和PE 54 一模一样.....
AC代码:
#include<bits/stdc++.h>
using namespace std;
//牌的定义
typedef struct tagCard
{
    char name;  //牌字符:2,3,, A
    char value; //牌字符在字符串中的索引
    char suit;  //花色
} Card;

typedef Card Item;

//两副牌,每幅各有5张牌
Card cardsBlack[5];
Card cardsWhite[5];
//用于在两副牌达到相同level时的辅助比较数组
int orderBlack[5];
int orderWhite[5];

char line[32];


//所有牌的值,其中10用T表示
char CardValues[]="23456789TJQKA";

//判断t1-t2的差值,即两副牌差值
int lessthan(Item t1, Item t2)
{
    return (t1.value<t2.value)? 1:0;    
}

// return t1-t2
int diffence(Item t1, Item t2)
{
    return (t1.value - t2.value);
}

//交换a[]的i,j项
void exchange(Item a[], int i, int j)
{
    char n1=a[i].name;
    char v1=a[i].value;
    char s1=a[i].suit;
    
    a[i].name=a[j].name;
    a[i].value=a[j].value;
    a[i].suit=a[j].suit;
    
    a[j].name=n1;
    a[j].value=v1;
    a[j].suit=s1;
}
 
//排序 
void SelectionSort(Item a[], int left, int right)
{
    int i,j,min;
    for(i=left; i<right; i++)
    {
        min=i;
        for(j=i+1; j<=right; j++)
            if(lessthan(a[j],a[min])) min=j;
        exchange(a, i, min);
    }
}


//把读取的这一行输入给两副牌数组Black , White 
//2H 3D 5S 9C KD 2C 3H 4S 8C AH
void InitCards()
{
    int i;
    for(i=0;i<5;i++)
    {
        cardsBlack[i].name=line[3*i];
        cardsBlack[i].suit=line[3*i+1];
        cardsBlack[i].value=strchr(CardValues, cardsBlack[i].name)-CardValues;
        
        cardsWhite[i].name=line[3*i+15];
        cardsWhite[i].suit=line[3*i+16];
        cardsWhite[i].value=strchr(CardValues, cardsWhite[i].name)-CardValues;
    }
}

//把两副牌按照从小到大的顺序排好序
void SortCards()
{
    SelectionSort(cardsBlack, 0, 4);
    SelectionSort(cardsWhite, 0, 4);
}

//判断从index起始的,向后数4张牌是否构成一副炸弹,即牌值相同!
int IsBomb(Item a[], int i)
{
    if(a[i+1].value==a[i].value&& a[i+2].value==a[i].value&& a[i+3].value==a[i].value)
         return 1;
    return 0;
}

//是否三张相同
int IsThree(Item a[], int i)
{
    if(a[i+1].value==a[i].value&& a[i+2].value==a[i].value)
        return 1;
    return 0;
}

//是否两张相同的对
int IsPair(Item a[], int i)
{
    if(a[i+1].value==a[i].value)
        return 1;
    return 0;
}

//是否5张牌的牌值连续
int IsStraight(Item a[])
{
    if((a[1].value-a[0].value)==1&& (a[2].value-a[1].value)==1&& (a[3].value-a[2].value)==1&& (a[4].value-a[3].value)==1 )
        return 1;
    return 0;
}

//是否5张牌都是同花色
int IsFlush(Item a[])
{
    if(a[1].suit==a[0].suit&& a[2].suit==a[0].suit&& a[3].suit==a[0].suit&& a[4].suit==a[0].suit)
        return 1;
    return 0;
}

//得到某副已经排好序的牌等级(同花顺最高!,杂牌最低)
//order是等级相同时的辅助比较值
int GetLevel(Item a[], int order[])
{
    int level,i,t1,t2,t3;
    order[0]=order[1]=order[2]=order[3]=order[4]=0;
    
    //level 9 - Straight flush. 同花顺,花色相同,并且牌连续
    level=9;
    if(IsStraight(a) && IsFlush(a))
    {
        order[0]=a[4].value;
        return level;
    }
    
    //level 8 - Four of a kind. 有4相同值的牌,即一副炸弹 
    level--;
    if(IsBomb(a, 0) || IsBomb(a, 1))
    {
        //注意如果有4张相同的牌,则a[1]一定位于这4帐牌之中
        order[0]=a[1].value;
        return level;
    }
    
    //level 7 - Full House. 有3张牌是相同值,另外2张牌也是相同值,OOOXX, XXOOO
    level--;
    if( (IsThree(a,0) && IsPair(a,3)) || (IsThree(a, 2) && IsPair(a, 0)) )
    {
        //XXXOO* Ranked by the value of the 3 cards. 
        order[0]=a[2].value;
        return level;
    }
    
    //level 6 - Flush. 5张牌同花色
    level--;
    if(IsFlush(a))
    {
        //If the highest cards have the same value, the hands are ranked by the next highest
        //order中是从大到小排列的牌值,用于判别大小
        for(i=0;i<5;i++) order[i]=a[4-i].value;
        return level;
    }
    
    //level 5 - Straight. 一条龙,即5张牌的值连续.
    level--;
    if(IsStraight(a))
    {
        order[0]=a[4].value;//ranked by their highest card. 
        return level;
    }
    
    //level 4 - Three of a Kind. 有三张相同值。OOOXY,XOOOY,XYOOO
    level--;
    if(IsThree(a,0) || IsThree(a,1) || IsThree(a,2))
    {
        order[0]=a[2].value;//ranked by the value of the 3 cards. 
        return level;
    }
    
    //level 3 - Two Pairs. 两副对,另一个杂牌的索引用i来记录.
    level--;
    if(  (i=0, IsPair(a,1) && IsPair(a,3))         /*-OOII*/
        || (i=2, IsPair(a,0) && IsPair(a,3))        /*OO-II*/
        || (i=4, IsPair(a,0) && IsPair(a,2)) )    /*OOII-*/
    {
        order[0]=a[3].value;/*I: max pair's value;*/
        order[1]=a[1].value;/*O: min pair's value;*/
        order[2]=a[i].value;/*-: remaining card;  */
        return level;
    }
    
    //level 2 - Pair. 一副对;OOxyz, xOOyz, xyOOz, xyzOO
    /*i存储Pair的位置,t1,t2,t3存储其他值的位置 */
    level--;
    if(  (i=0, t1=4, t2=3, t3=2, IsPair(a,0))        /*OOxyz*/
        || (i=1, t1=4, t2=3, t3=0, IsPair(a,1))        /*xOOyz*/
        || (i=2, t1=4, t2=1, t3=0, IsPair(a,2))        /*xyOOz*/
        || (i=3, t1=2, t2=1, t3=0, IsPair(a,3)) )    /*xyzOO*/
    {
        /*ranked by the value of the cards forming the pair. 
          If these values are the same, the hands are ranked 
          by the values of the cards not forming the pair, 
          in decreasing order. */
        order[0]=a[i].value;
        order[1]=a[t1].value;
        order[2]=a[t2].value;
        order[3]=a[t3].value;
        return level;
    }
    
    //level 1 - High Card. 完全的杂牌。不构成上诉任何情况,从大到小比
    level--;
    for(i=0;i<5;i++) order[i]=a[4-i].value;
    return level;
}

int main()
{
    int levelBlack, levelWhite, i;
    int ans=0;
    //freopen("poker.txt","r",stdin);
    while(gets(line)!=NULL && strlen(line)>2)
    {
        InitCards();    //把读入的字符串设置到数组中
        SortCards();   //把两副牌都排好序
        levelBlack=GetLevel(cardsBlack, orderBlack);
        levelWhite=GetLevel(cardsWhite, orderWhite);
        
        //比较两副牌
        if(levelBlack > levelWhite){
        	printf("Black wins.\n");
			//ans++;
		}
            
        else if(levelBlack < levelWhite)
            printf("White wins.\n");
        
        //等级相同 
        else
        {
            //级别相同,需要比较order数组
            for(i=0;i<5;i++)
            {
                if(orderBlack[i]>orderWhite[i])
                {
                    printf("Black wins.\n");
                    //ans++;
                    break;//已经比较出结果!
                }
                else if(orderBlack[i]<orderWhite[i])
                {
                    printf("White wins.\n");
                    break;
                }
            }
            //依然未分出胜负,则平局!
            if(i==5) printf("Tie.\n");
        }
    }
    //printf("%d",ans);
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值