牌组的题目

  1. 斗地主

难度:★★★★☆

考察知识点:C语言、排序

题目描述

阿伟是《欢乐斗地主》游戏的爱好者,在跟彬彬一起玩游戏的过程中,他把刚充值的648欢乐豆输了个精光。恼羞成怒的阿伟决定研发一个斗地主辅助器,帮助他赚取欢乐豆。

阿伟决定先实现一个相对简单的功能:输出他的牌里最长且最大的顺子(优先保证最长,其次保证最大)。

我们对“顺子”的定义如下:必须是数组 [3, 4, 5, 6, 7, 8, 9, 10, J, Q, K, A]连续的一部分,因此我们认为一张单牌也是顺子

为了简单起见,我们忽略扑克牌的花色和大小王,认为输入只能是 2/3/4/5/6/7/8/9/10/J/Q/K/A 中的任意一个。

2 不能当作顺子的一部分。

使用C或C++语言编写程序。

输入格式

阿伟会把自己的牌(可能是乱序的,且有重复)输入为以空格隔开的一行。

小写的 j/q/k/a 认为是错误输入。

输出格式

如果阿伟输入斗地主中不存在的牌,输出 Illegal cards

如果牌里不存在顺子(例如2 2 2 2),输出 No straight

否则,输出所求顺子序列,以空格隔开,不要有多余的内容。

输入输出样例

程序应当能检测各种错误情况。

输入 #1

Just Do It

输出 #1

Illegal cards

输入 #2

abcdefg$# <><> ABAB

输出 #2

Illegal cards

如果用户输入了空行,程序也认为是错误输入。

输入 #3

 

输出 #3

Illegal cards

但是,如果用户输入中存在多余的空格,程序应能正确解析,而不是报出错误。

输入 #4

4 5 6 7 10 J Q K

输出 #4

10 J Q K

如果存在多个顺子,程序应该优先选择最长的顺子,在同样长度的顺子中,选择最大的顺子。

输入 #5

3 4 5 6 7 8 10 J Q K A

输出 #5

3 4 5 6 7 8

输入 #6

3 4 5 6 7 10 J Q K A

输出 #6

10 J Q K A

为了简化题目,我们规定顺子的长度可以是1。这意味着如果输入的序列中没有顺子,程序应当输出最大的那张牌。

输入 #7

3 5 7 9 J K

输出 #7

K

2永远都不是顺子的一部分,因此如果最大的那张牌是2,则应该输出第二大的那张牌。

输入 #8

3 5 7 9 J A 2

输出 #8

A

如果牌里完全不存在顺子,输出 No straight

输入 #9

2 2 2 2

输出 #9

No straight

如果多张同样的牌能组成连对/飞机,你依旧只需要输出顺子。

输入 #10

3 3 4 4 5 5 5 6 6 6

输出 #10

3 4 5 6

输入 #11

3 4 7 8 K K K K A A A A 2

输出 #11

K A

数据范围

  • 对于70%的测试数据,我们保证牌的数量小于$$10^4$$,输入数据的总字符数不超过$$10^5$$。

  • 对于100%的测试数据,我们保证牌的数量小于$$10^6$$,输入数据的总字符数不超过$$10^7$$。

我们将在 Intel Core i7-1165G7 @ 2.80GHz CPU 上评测你的程序,对于任意一条数据,你的程序需要在1秒内计算出结果。

 

// 斗地主.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include<iostream>
#include<string.h>
#include<string>
#include<algorithm>


using namespace std;

static void insertionsort(int arr[], int n)//插入排序
{
    for (int i = 1; i < n; i++)
    {
        int key = arr[i];
        int j = i - 1;
        while (j >= 0 && arr[j] > key)
        {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = key;
    }
}

static int char_to_int(string s)//将字符换成数字,方便排序
{
    if (s == "J")
    {
        return 11;
    }
    else if (s == "Q")
    {
        return 12;
    }
    else if (s == "K")
    {
        return 13;
    }
    else if (s == "A")
    {
        return 14;
    }
    else if (s == "10")
    {
        return 10;
    }
    else {
        return stoi(s);
    }
}

static string int_to_char(int a)//由数字重新得到字符串
{
    if (a == 11) {
        return "J";
    }
    else if (a == 12) {
        return "Q";
    }
    else if (a == 13) {
        return "K";
    }
    else if (a == 14) {
        return "A";
    }
    else if (a == 10)
    {
        return "10";
    }
    else {
        return to_string(a);
    }
}

int main() {
    string str;
    string arr[100];
    string str1[13] = { {"2"},{"3"},{"4"},{"5"},{"6"},{"7"},{"8"},{"9"},{"10"},{"J"},{"Q"},{"K"},{"A"}};//可能出现的所有牌
    int index = 0, flag = 1;
    while (cin >> str) {//string遇到空格会停止 
        arr[index++] = str;
        for (int i = 0; i < 13; i++)//判断输入的牌是否合法(借用flag来标记)
        {
            if (str == str1[i])
            {
                flag = 1;
                break;
            }
            else flag = 0;
        }
        char ch = getchar();//通过getchar()来判断最后输入回车符结束 
        if (ch == '\n') break;
        if (ch == ' ') continue;//多余的空格忽略
    }
    if (flag == 0)cout << "Illegal cards";//输入时有非法牌就输出‘illegalcards’
    if (flag == 1)//输入的牌合法
    {
        int n[50]{};
        
        for (int j = 0; j < index; j++)
        {
            n[j] = char_to_int(arr[j]);
        }
        insertionsort(n, index);
        if (n[index-1] == 2) cout << "No straight";//不存在顺子
        else 
        {
            int count[20]{},tmp[20]{}, y = 0, set=0;//count记录顺子长度,tmp记录每个顺子最后一个数,y记录顺子个数,set指示最长的顺子
            for (int m = 0; m < index; m++)
            {
                if (n[m] != 2)
                {   
                    if ((n[m + 1] - n[m]) == 1) count[y]++;
                    else if (n[m] == n[m + 1]) continue;
                    else 
                    {
                        tmp[y] = n[m];
                        y++;
                    }          
                }
            }
            for (int k = 0; k < y; k++)//set找出最长的顺子
            {
                if (count[k] >= count[k + 1]) set = k;
                else set = k + 1;
            }
            for (int h = count[set]; h >=0; h--)//由下标输出找出的最长顺子
            {
                cout << int_to_char(tmp[set] - h) << " ";
            }
        }
    }
    return 0;
}


 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值