TypeCodes

由学生按某规则依次报数的游戏引发的问题

前段时间Q群里有提问如下,编写程序解决一个学生按规则依次报数的体育游戏问题。编程语言不限,Java, C#, Ruby, C++, Js, Python, Scala, objective-C统统可以,小语种也没问题。

学生按某规则依次报数的游戏

1 问题描述:
你是一名体育老师,在某次课距离下课还有五分钟时,你决定搞一个游戏。此时有100名学生在上课。游戏的规则是:
1. 你首先说出三个不同的特殊数,要求必须是个位数,比如3、5、7。
2. 让所有学生拍成一队,然后按顺序报数。
3. 学生报数时,如果所报数字是第一个特殊数(3)的倍数,那么不能说该数字,而要说Fizz;如果所报数字是第二个特殊数(5)的倍数,那么要说Buzz;如果所报数字是第三个特殊数(7)的倍数,那么要说Whizz。
4. 学生报数时,如果所报数字同时是两个特殊数的倍数情况下,也要特殊处理,比如第一个特殊数和第二个特殊数的倍数,那么不能说该数字,而是要说FizzBuzz, 以此类推。如果同时是三个特殊数的倍数,那么要说FizzBuzzWhizz。
5. 学生报数时,如果所报数字包含了第一个特殊数,那么也不能说该数字,而是要说相应的单词,比如本例中第一个特殊数是3,那么要报13的同学应该说Fizz。如果数字中包含了第一个特殊数,那么忽略规则3和规则4,比如要报35的同学只报Fizz,不报BuzzWhizz。

现在,我们需要你完成一个程序来模拟这个游戏,它首先接受3个特殊数,然后输出100名学生应该报数的数或单词。比如,

输入
3,5,7
输出(片段)

1
2
Fizz
4
Buzz
Fizz
Whizz
8
Fizz
Buzz
11
Fizz
Fizz
Whizz
FizzBuzz
16
17
Fizz
19
Buzz
…
一直到100
2 解决方法:

这个问题主要是要理解提到的游戏规则,然后为每个学生对应的序号匹配出对应的rule模式,这样问题就解决了。下面是自己用C写的解决方法:

  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
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/**
 * 游戏体育老师写3个个位数,100名同学按一定规则报数的问题
 * @filename: game.c
 * @author  : vfhky  2014.10.25  https://typecodes.com
 */

#include "stdio.h"
#include "string.h"
#define TotalNum 100

/**
 * 获取一个1000范围内的整形数据的各个位
 * @param [in]  number  学生序号
 * @param [in/out]  highnum 将每个位依次保存到数组
 * return 0: 成功; -1:整数超出范围
 */
int gethighnum( int number, char highnum[] )
{
    if( number < 10 )
    {
        *highnum = number + 48;
        return 1;
    }
    else if( number < 100 )
    {
        *highnum = number/10 + 48;
        *(highnum+1) = number%10 + 48;
        return 1;
    }
    else if( number < 1000 )
    {
        *highnum = number/100 + 48;
        *(highnum+1) = ( number - (number/100)*100 )/10 + 48;
        *(highnum+2) = number%100 + 48;
        return 1;
    }
    else
        return -1;
}


/**
 * 将学生序号按照规则3/4/5处理: 最后匹配出对应的字符串
 * @param [in]  inputa  老师输入的第一个数字
 * @param [in]  inputb  老师输入的第二个数字
 * @param [in]  inputc  老师输入的第三个数字
 * @param [in]  number  学生序号
 * @param [in/out]  matchstr    匹配的字符串
 * @param [in/out]  flag        是否包含了匹配数字, 0:未包含   1: 包含
 * return -1: 该学生序号不合法;  0:未包含第一个数字;  1:包含第一个数字;
 */
int rules( int inputa, int inputb, int inputc, int number, char matchstr[], int * flag )
{
    int result;
    char highnum[4] = { 0 };    //整数的各个位
    *flag = 0;
    result = gethighnum( number, highnum );     //获取该整数的所有高位字符highnum
    if( result != 1 )
        return -1;

    /* 检测是否包含第一个特殊数字 */
    for( result=0; result<strlen(highnum); result++ )
    {
        if( inputa == highnum[result] - 48 )
            return 1;
    }

    memset( matchstr, 0x30, 4 );
    if( number % inputa == 0 )
    {
        *matchstr = 0x31;
        *flag = 1;
    }

    if( number % inputb == 0 )
    {
        *(matchstr+1) = 0x32;
        *flag = 1;
    }

    if( number % inputc == 0 )
    {
        *(matchstr+2) = 0x33;
        *flag = 1;
    }

    return 0;
}


int main( int argc, char * argv[] )
{
    int stuinx = 1;     //学生序号, 从1开始报数
    int a, b, c;        //老师输入的三个整型数据
    int result;         //临时数据

    /* 初始化对应的三个字符串数据 */
    char arr1[5] = "Fizz";
    char arr2[5] = "Buzz";
    char arr3[6] = "Whizz";
    char arr[14];

    /* 老师输入3个整形数据 */
    printf( "Please input three integer number:\n eg. 3, 5, 7\n" );
    scanf( "%d, %d, %d", &a, &b, &c );
    if( a>0xa || b>0xa || c>0xa )
    {
        printf( "You should inpute three integer number!\n" );
        return -1;
    }
    printf( "You have inputed three integer number:[%d], [%d], [%d]\n", a, b, c );

    int flag, *p;
    p = &flag;
    char matchstr[4] = { 0 };

    /* 学生开始依次报数 */
    for( ; stuinx<TotalNum+1; stuinx++ )
    {
        /* 每次循环重新初始化数据 */
        flag = 0;
        memset( arr, 0x00, sizeof(arr) );
        memset( matchstr, 0x30, sizeof(matchstr) );

        /* 根据规则获取匹配字符串matchnum以及是否包含匹配字符的标志*p */
        result = rules( a, b, c, stuinx, matchstr, p );
        if( result == -1 )
            printf( "The total number of students can not be more than 1000!\n" );
        else if( result )
        {
            strcpy( arr, arr1 );
            printf( "No.[%d] says [%s]\n", stuinx, arr );
            continue;
        }
        if( *p )
        {
            /* 如果包含了非第一个特殊数字 */
            for( result=0; result<strlen(matchstr); result++ )
            {
                if( matchstr[result] == 0x31 )
                    strcat( arr, arr1 );
                else if( matchstr[result] == 0x32 )
                    strcat( arr, arr2 );
                else if( matchstr[result] == 0x33 )
                    strcat( arr, arr3 );
            }
            printf( "No.[%d] says [%s]\n", stuinx, arr );
        }
        else
            printf( "No.[%d] says [%d]\n", stuinx, stuinx );
    }

    return 0;
}
3 测试结果

GCC编译后执行,结果如下图所示。但发现没有任何一位学生在报数时,需要报包含FizzBuzzWhizz全部这三个单词的组合,例如不会出现题目规则4中所述的FizzBuzzWhizz。原因可以直接从前面的几条规则中推导出来。

测试结果

打赏支持

Comments »