新形态C语言程序设计游戏化任务教程:第6章17关-20关

前言:

题目链接
进入链接后,点击实践项目,以下题目为6.8.17到6.8.20,

古老的纸牌游戏

任务描述:
本题所述的麻将纸牌只包括3大类别的牌:条、饼、万(不包括老千、红花和白花)。每大类的牌点数都有从1至9,共27种牌,每种牌有4张,一副牌只取108张。
和牌规则:
5张牌和(音:胡)牌的规则如下:
1.必须有一个对子,即两张相同的牌,称为“掌”,比如:两个2饼做掌,两个4条做掌等。
2.剩余的3张牌,如果正好形成“哈子”(3个一样的牌,如3个2饼,麻将中称为一刻)或者“一趟副”(同种类点数连续,如1条、2条、3条),就可以和牌了。
3.输入的牌肯定是4张。
4.条用T表示,饼用B表示,万用W表示。
也可以理解为和牌类型有以下几种(11表示一对,123表示一副、111表示一刻):
(1)11、123(1副1对)
(2)11、111(1哈1对)
假设你手中有4张牌,如果加上别人打出手的1张牌或你自己再摸1张牌,就构成和牌,则称“有叫儿”(麻将称为听牌)。
给你4张牌,你知道自己是否“有叫儿”并和什么牌吗?

输入格式:

输入共一行,代表一组数据(一手牌)。
在一行中包含以1个空格分隔的4个数据,每个数据由1个数字加1个大写字母构成,代表1张纸牌,4个数据代表一手牌。(例如:1T代表1条、2W代表2万、9B代表9饼)。

输出格式:

该组数据如果“有叫儿”,则依次输出可以和的牌(叫儿),如果有多个“叫儿”,按“条、饼、万”的顺序输出,同一种类的牌,按点数从小到大输出,每个“叫儿”之后输出一个圆点句号。
该组数据如果“没有叫儿”,则输出:No jiaor。

输入样例(平和2张):

4B 4B 3T 4T

输出样例:

2T.5T.

输入样例(和对倒2张):

1T 6W 6W 1T

输出样例:

1T.6W.

输入样例:(和边张)

1T 2T 6B 6B

输出样例:

3T.

输入样例(和卡):

4T 2T 6W 6W

输出样例:

3T.

输入样例(和单吊1张):

4T 2T 6W 3T

输出样例:

6W.

输入样例(和单吊或和卡):

4T 2T 3T 3T

输出样例:

3T.

输入样例(平和、单吊):

4T 4T 4T 3T

输出样例:

2T.3T.5T.

输入样例(没和):

4T 4T 4T 4T

输出样例:

No jiaor

输入样例(没和):

4T 4T 4W 8B

输出样例:

No jiaor

解题思路:

还记得上次写扑克,这次是写麻将,麻将的规则比起扑克要麻烦一些,从题目给出了很多的样例也可以看出

  • 使用结构体对麻将卡牌进行拆分

  • 输出是要按牌型排序的,用一个数组type存储牌型,用序号表示优先级

  • 记住一副牌里一种卡牌只有四张,如果手上卡牌4张一样的话是没法有叫儿的

  • 可以分析一下,一共有4张牌,对于牌型,若三种牌型卡牌分布为1 1 2是不可能有叫儿的,

  • 不论顺序,要有叫儿的话,只有三种牌型分布4 0 0,2 2 0,3 1 0

  • 先分析4 0 0的情况,也就是手上4张牌牌型一样,这种是情况最复杂的,按我写的代码的思路按顺序说情况,
    先是4张牌点数连一起,那可以和的牌只有牌只有两张,中间的不能动,与最小点数或最大点数凑成对子
    三张牌点数连一起,以实例展示吧,比如4T 2T 3T 3T,这种情况只能再给一张与那张对子一样的牌,还有就是4T 2T 3T 7T,与剩下那张凑个对子
    三张卡牌相同,那就要判断剩下那张卡牌与这三张的点数关系,还要判断边界关系,比如 1T 2T 2T 2T,这种卡在边界的,就只有两种,一种自身,还有组成一个顺子,不在边界且差为1,比如4T 4T 4T 3T,除了自身,还可以组两种顺子,还有差为2的,比如4T 4T 4T 2T,一种自身,一种顺子,当差大于2时,就只有自身了

  • 3 1 0的情况,只有那三张牌凑成了顺子或一样的,才行,只有一种就剩下那张牌再来一张才能和

  • 2 2 0的情况,只有两两为对子或一为对子,另两张点数相连才行,若为对子就输出对子的牌,注意按从小到大输出,有对子就只能凑对子了

参考代码:

#include<stdio.h>

char type[3] = {'T', 'B', 'W'};//表示牌型优先级
struct node {
    char model;//牌型
    int number[10];//存储该牌型对应的点数的牌,比如若有点数为1的牌,则number[1]++
    int flag;//表示在该牌型有几张牌
} card[3];//三种牌型

void print() {//没有叫儿
    printf("No jiaor");
}

void flag_1() {//处理当其他三张牌凑成了顺子或一样时的情况,且牌型与那三张牌不同
    for (int i = 0; i < 3; i++) {
        if (card[i].flag == 1) {
            for (int j = 1; j <= 9; j++) {
                if (card[i].number[j]) {//找出那张牌,再给一张一样的牌就是一个对子,就和了
                    printf("%d%c.", j, card[i].model);
                    return;
                }
            }
        }
    }
}

int same_card(int i) {//三张牌凑成了顺子或一样的
    for (int j = 1; j <= 7; j++) {
        if ((card[i].number[j] && card[i].number[j + 1] && card[i].number[j + 2]) || card[i].number[j] == 3) {
            flag_1();
            return 1;
        }
    }
    return 0;
}
int Straight(int i)//4张卡牌顺子
{
    for(int j=1;j<=6;j++)
    {
        if(card[i].number[j] && card[i].number[j + 1] && card[i].number[j + 2]&&card[i].number[j + 3])
        {
            printf("%d%c.%d%c.",j,card[i].model,j+3,card[i].model);
            return 1;
        }
    }
    return 0;
}
int _Straight(int i)//三张顺
{
    int vis[10]={0};
    int j;
    for(j=1;j<=7;j++)
    {
        if((card[i].number[j] && card[i].number[j + 1] && card[i].number[j + 2]))
        {
            vis[j]=vis[j+1]=vis[j+2]=1;
            break;
        }
    }
    if(j==8)//j==8意味着没有顺子
    return 0;
    for(j=1;j<=9;j++)
    {
        if(vis[j]&&card[i].number[j]==2)//情况例:4T 2T 3T 3T
        {
            printf("%d%c.", j, card[i].model);
            return 1;
        }
        if(!vis[j]&&card[i].number[j])
        {
            printf("%d%c.", j, card[i].model);
            return 1;
        }
    }
    return 0;
}
void same_card_4(int i,int j)
{
    int k;
    for(k=1;k<j;k++)
    {
        if(card[i].number[k])
        {
            break;
        }
    }
    if(k<j)
    {
        if(j-k==1)//情况例:4T 4T 4T 3T
        {
            if(k>1)
            printf("%d%c.",k-1,card[i].model);
            printf("%d%c.",k,card[i].model);
            printf("%d%c.",k+2,card[i].model);
            return;
        }
        else if(j-k==2)//情况例:4T 4T 4T 2T
        {
            printf("%d%c.",k,card[i].model);
            printf("%d%c.",k+1,card[i].model);
            return;
        }
        printf("%d%c.",k,card[i].model);//差大于2
        return;
    }
    for(k=j+1;k<=9;k++)
    {
        if(card[i].number[k])
        {
            break;
        }
    }
    if(k<=9)
    {
        if(k-j==1)//情况例:4T 4T 4T 3T
        {
            printf("%d%c.",k-2,card[i].model);
            printf("%d%c.",k,card[i].model);
            if(k<9)
            printf("%d%c.",k+1,card[i].model);
            return;
        }
        else if(j-k==2)//情况例:4T 4T 4T 2T
        {
            printf("%d%c.",k-1,card[i].model);
            printf("%d%c.",k,card[i].model);
            return;
        }
        printf("%d%c.",k,card[i].model);//差大于2
        return;
    }
}
void flag_2()
{
    int count=0;
    int number_2[2];
    int Pairs[2]={0};
    int count_i;
    int Pairs_i;
    for(int i=0;i<3;i++)
    {
        if(card[i].flag==2)
        {
          for(int j=1;j<=9;j++)
          {
              if(card[i].number[j]==2)
              {
                number_2[count++]=j;
                if(count==2)
                {
                   printf("%d%c.",number_2[0],card[count_i].model);
                    printf("%d%c.",number_2[1],card[i].model);
                    return;
                }
                count_i=i;
                break;
              }
              else if(j<9&&card[i].number[j]&&card[i].number[j+1])
              {
                  if(j>1)
                  Pairs[0]=j-1;
                  if(j<8)
                  Pairs[1]=j+2;
                  Pairs_i=i;
                  break;
              }
              else if(j<8&&card[i].number[j]&&card[i].number[j+2])
              {
                  Pairs[0]=j+1;
                  Pairs_i=i;
                  break;
              }
          }
        }
    }
    if(count==1)
    {
    if(Pairs[0])
    printf("%d%c.",Pairs[0],card[Pairs_i].model);
    if(Pairs[1])
    printf("%d%c.",Pairs[1],card[Pairs_i].model);
    if(!(Pairs[0]||Pairs[1]))
    print();
    return;
    }
    print();
}
void solve() {
    for (int i = 0; i < 3; i++) {
        if (card[i].flag == 4) {
            if(Straight(i))
            return;
            if(_Straight(i))
            return;
            for(int j=1;j<=9;j++)
            {
                if(card[i].number[j]==3)//三张卡牌相同
                {
                    same_card_4(i,j);//传入j,从j开始往两头找剩下那张牌,也便于判断剩下那张牌与这三张卡牌的点数关系
                    return;
                }
            }
        }
        if (card[i].flag == 3) {
            if(!same_card(i))
            {
                print();
            }
            return;
        }
    }
    flag_2();
}

int main() {
    for (int i = 0; i < 3; i++)
        card[i].model = type[i];
    char model;
    int number;
    while (~scanf("%d%c", &number, &model)) {//获取输入的卡牌
        for (int i = 0; i < 3; i++) {
            if (card[i].model == model) {
                card[i].number[number]++;
                if (card[i].number[number] == 4) {//当有4张卡牌一样时,则不可能有叫儿
                    print();
                    return 0;
                }
                card[i].flag++;
                break;
            }
        }
    }
    solve();
    return 0;
}

餐饮服务质量调查打分

任务描述
在商业和科学研究中,人们经常需要对数据进行分析并将结果以直方图的形式显示出来,这会大大增加这些数据的直观性,也便于数据的分析与对比。下面以顾客对餐饮服务打分为例,输入一个正整数repeat (0<repeat<10),做repeat次下列运算:
输入一个正整数n(1≤n≤20),表示有n个学生被邀请来给自助餐厅的食品和服务质量打分,分数划分为1~5这5个等级(1表示最低分,5表示最高分),试统计调查结果,并用*打印出如下形式的统计结果直方图。

输入格式:

第1个整数repeat为数据组数,一共有repeat组数据,请分别处理每组数据,每组数据输出一个直方图。
接下来为repeat组数据,每组数据的第1个数为打分人数n,接下来为这n个人的n个打分。

输出格式:

按输出样例的样式输出结果。

输入样例:

1
10
1 2 2 3 3 5 2 2 3 5

输出样例:

  *
  * *
  * *   *
* * *   *
1 2 3 4 5

输入样例:

2
10
1 1 1 1 1 2 3 4 5 5
20
1 1 1 2 2 2 3 3 3 4 5 1 2 3 4 2 2 3 5 2

输出样例:

*
*
*
*       *
* * * * *
1 2 3 4 5
  *
  *
  * *
* * *
* * *
* * * * *
* * * * *
1 2 3 4 5

解题思路:

这题比起前面的纸牌游戏就简单不少了,就是画图

  • 仍然是用结构体处理,number和score像构成了坐标一样,嘿嘿

参考代码:

#include<stdio.h>
struct node
{
    int number;//打该分的人数
    int score;//分数
}student[6];
int max=0;//打分最多,也就是图里的最高纵坐标
void solve()
{
    for(int i=max;i>0;i--)
    {
        int flag=0;//统计图中空的地方
        int t=0;
        for(int j=1;j<=5;j++)
        {
            if(student[j].number>=i)
            {
                for(int i=0;i<flag;i++)
                {
                    printf("  ");
                }
                flag=0;
                if(t)
                printf(" ");
                printf("*");
                t++;
            }
            else
            flag++;
        }
        printf("\n");
    }
}
int main()
{
    int repeat;
    scanf("%d",&repeat);
    int n,a;
    for(int i=1;i<=5;i++)
    {
        student[i].score=i;
    }
    while(repeat--)
    {
        scanf("%d",&n);
        for(int i=1;i<=5;i++)
        student[i].number=0;
        for(int i=0;i<n;i++)
        {
          scanf("%d",&a);  
          for(int j=1;j<=5;j++)
          {
              if(a==student[j].score)
              {
                  student[j].number++;
                  if(max<student[j].number)
                  max=student[j].number;
                  break;
              }
          }
        }
        solve();
        printf("1 2 3 4 5\n");
    }
    return 0;
}

月历

任务描述
X想知道某年某月的日历,你能为他编程输出吗?

输入格式:

输入一行,两个正整数,分别代表年份和月份。

输出格式:

严格按样例格式输出一个月的日历。
第1行输出月份简称和年份,中间有个圆点和空格。
第2行输出表头,为星期一至星期日的缩写,每个单词之间一个空格。
第3行为28个减号。
接下来的几行是日历内容,每个日期输出时占3列,日期前后之间再加1个空格,保证与相对应的星期名称右对齐。

输入样例:

2019 9

输出样例:

SEP. 2019
Mon Tue Wed Thu Fri Sat Sun
---------------------------
                          1
  2   3   4   5   6   7   8
  9  10  11  12  13  14  15
 16  17  18  19  20  21  22
 23  24  25  26  27  28  29
 30

提示

重要提示:190011日是星期一。
星期一:Monday 缩写:Mon.
星期二:Tuesday 缩写:Tue.
星期三:Wednesday 缩写:Wed.
星期四:Thursday 缩写:Thu.
星期五:Friday 缩写:Fri.
星期六:Saturday 缩写:Sat.
星期日:Sunday 缩写:Sun.
一月份JAN.
二月份FEB.
三月份MAR.
四月份APR.
五月份MAY.
六月份JUN.
七月份JUL.
八月份AUG.
九月份SEP.
十月份OCT.
十一月份NOV.
十二月份DEC.

解题思路:

还是画图,不过这个感觉有意思些,
不过我一开始没有看到提示里的1900年1月1日是星期一。用了蔡勒公式
蔡勒公式:
int h = (day + 2 * month + 3 * (month + 1) / 5 + year + year / 4 - year / 100 + year / 400 + 1) % 7;
day为日,month为月份,year为年份
h的值是几,即为星期几,
为0时,星期天

参考代码:

使用蔡勒公式版:

//请在此输入你的代码,复杂程序可先在Dev C++中运行调试后再提交
#include<stdio.h>
void print_month(int year,int month)
{
    switch(month)
    {
        case 1:
        printf("JAN. ");
        break;
        case 2:
        printf("FEB. ");
        break;
        case 3:
        printf("MAR. ");
        break;
        case 4:
        printf("APR. ");
        break;
        case 5:
        printf("MAY. ");
        break;
        case 6:
        printf("JUN. ");
        break;
        case 7:
        printf("JUL. ");
        break;
        case 8:
        printf("AUG. ");
        break;
        case 9:
        printf("SEP. ");
        break;
        case 10:
        printf("OCT. ");
        break;
        case 11:
        printf("NOV. ");
        break;
        case 12:
        printf("DEC. ");
        break;
    }
    printf("%d\n",year);
}
void print_week()
{
    printf("Mon Tue Wed Thu Fri Sat Sun\n");
}
int getWeek(int year,int month,int day)//蔡勒公式
{
    if(month<3)//如果给定日期在1月或2月(即month1为1或2),则需要将年份减1,将月份增加12。这是为了将这两个月视为前一年的13月和14月
    {
        month+=12;
        year--;
    }
    //int h=(sun+(13*(month1+1)/5)+year%100+(year%100/4)+(year/400)-2*(year/100))%7;
    int h=(day+2*month+3*(month+1)/5+year+year/4-year/100+year/400+1)%7;
    return h;
}
int main()
{
    int year,month;
    scanf("%d%d",&year,&month);
    print_month(year,month);
    print_week();
    for(int i=0;i<27;i++)
    printf("-");
    printf("\n");
    int k=year%100?year%4?0:1:year%400?0:1;
    int m[13]={0,31,28+k,31,30,31,30,31,31,30,31,30,31};
    int h=getWeek(year,month,1);
    int count=h;
    if(h==0)
    {
        for(int i=0;i<6;i++)
        printf("    ");
        count=7;
    }
    for(int i=1;i<h;i++)
    printf("    ");
    int t=0;
    for(int i=1;i<=m[month];i++)
    {
        if(t)
        printf(" ");
        printf("%3d",i);
        t++;
        if(count==7)
        {
            printf("\n");
            count=0;
            t=0;
        }
        count++;
    }
    return 0;
}

利用题目中的提示:

//请在此输入你的代码,复杂程序可先在Dev C++中运行调试后再提交
#include<stdio.h>
void print_month(int year,int month)
{
    switch(month)
    {
        case 1:
        printf("JAN. ");
        break;
        case 2:
        printf("FEB. ");
        break;
        case 3:
        printf("MAR. ");
        break;
        case 4:
        printf("APR. ");
        break;
        case 5:
        printf("MAY. ");
        break;
        case 6:
        printf("JUN. ");
        break;
        case 7:
        printf("JUL. ");
        break;
        case 8:
        printf("AUG. ");
        break;
        case 9:
        printf("SEP. ");
        break;
        case 10:
        printf("OCT. ");
        break;
        case 11:
        printf("NOV. ");
        break;
        case 12:
        printf("DEC. ");
        break;
    }
    printf("%d\n",year);
}
void print_week()
{
    printf("Mon Tue Wed Thu Fri Sat Sun\n");
}
int getWeek(int year,int month,int day)//蔡勒公式
{
    if(month<3)//如果给定日期在1月或2月(即month1为1或2),则需要将年份减1,将月份增加12。这是为了将这两个月视为前一年的13月和14月
    {
        month+=12;
        year--;
    }
    //int h=(sun+(13*(month1+1)/5)+year%100+(year%100/4)+(year/400)-2*(year/100))%7;
    int h=(day+2*month+3*(month+1)/5+year+year/4-year/100+year/400+1)%7;
    return h;
}
int fun(int year)//获取从1900到输入的年份的天数
{
    int days=0;
    for (int a = 1900; a < year; a++)
		{
			if (a % 400 == 0 || a % 4 == 0 && a % 100 != 0)
			{
				days+=366;
			}
            else
            days+=365;
		}
        return days;
}
int funweek(int year,int days)//判断星期几
{
    days+=fun(year);//总天数
    int h=days%7;
    return h;
}
int main()
{
    int year,month;
    scanf("%d%d",&year,&month);
    print_month(year,month);
    print_week();
    for(int i=0;i<27;i++)
    printf("-");
    printf("\n");
    int k=year%100?year%4?0:1:year%400?0:1;
    int m[13]={0,31,28+k,31,30,31,30,31,31,30,31,30,31};
    //int h=getWeek(year,month,1);
    int days=1;
    for(int i=1;i<month;i++)
    {
        days+=m[i];
    }
    int h=funweek(year,days);
    int count=h;
    if(h==0)
    {
        for(int i=0;i<6;i++)
        printf("    ");
        count=7;
    }
    for(int i=1;i<h;i++)
    printf("    ");
    int t=0;
    for(int i=1;i<=m[month];i++)
    {
        if(t)
        printf(" ");
        printf("%3d",i);
        t++;
        if(count==7)
        {
            printf("\n");
            count=0;
            t=0;
        }
        count++;
    }
    return 0;
}

鲜花数

任务描述
鲜花数是指一个N位正整数(7≥N≥3),它的每个位上的数字的N次幂之和等于它本身。
例如:
153=13+53+33 ,1634=14+64+34+44

当N=3时,花朵数又称为水仙花数;

当N=4时,花朵数又称为四叶玫瑰数;

当N=5时,花朵数又称为五角星数;

当N=6时,花朵数又称为六合数;

当N=7时,花朵数又称为北斗数,等等。

要求编写程序,输出所有N位花朵数。

输入格式:

一个整数N(7≥N≥3

输出格式:

从小到大输出所有N位鲜花数,一个数一行。

输入样例:

3

输出样例:

153
370
371
407

输入样例:

4

输出样例:

1634
8208
9474

解题思路:

这题没什么好说的,就是N为几,就去遍历10N-1到10N的数,就是拓展了下那道经典的水仙花的题目

参考代码:

#include <stdio.h>
#include <math.h>

// 函数声明,
int isFlower(int number, int N);
void findFlower(int N);

int main() {
    int N;
    scanf("%d", &N);
    findFlower(N);
    return 0;
}

// 检查一个数是否为鲜花数
int isFlower(int number, int N) {
    int originalNumber = number;
    int sum = 0;
    while (number > 0) {
        int digit = number % 10;
        sum += pow(digit, N);
        number /= 10;
    }
    return sum == originalNumber;
}

// 找到并打印所有N位鲜花数
void findFlower(int N) {
    int lower = pow(10, N - 1);
    int upper = pow(10, N);
    for (int i = lower; i < upper; i++) {
        if (isFlower(i, N)) {
            printf("%d\n", i);
        }
    }
}

  • 16
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值