(创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹)
目录
第1关:模拟投掷骰子游戏:
题目:
本关任务:模拟掷双骰子游戏,游戏规则:每轮投两次骰子,取两次的和,第一轮若和为
7
或11
则获胜,游戏结束。
- 例一:
和为
11
,则显示:'Round 1: Score:11 Success!'
若和为2
、3
或12
则输了,失败结束,
- 例二:
和为
12
,则显示:'Round 1: Score:12 Failed!'
若和为其他数字,则将第一轮两次骰子点数的和(假定为8
)作为自己的点数,继续第二轮,第三轮,……,直到某轮两次骰子点数的和等于该点数(第一轮两次投掷点数和)则获胜,若中间某轮两次投掷骰子点数的和为7
,则输掉游戏。对应显示:
'Round 1: Score:8 Continue!'
'Next rounds: Score 8:Success, Score 7:Failed, others:Continue'
'Round 2: Score:4 Continue!'
'Round 3: Score:6 Continue!'
'Round 4: Score:9 Continue!'
'Round 5: Score:7 Failed!'
测试输入:
1
预期输出:
Round 1: Score:7 Success!
测试输入:
18
预期输出:
'Round 1: Score:8 Continue!'
'Next rounds: Score 8:Success, Score 7:Failed, others:Continue'
'Round 2: Score:4 Continue!'
'Round 3: Score:6 Continue!'
'Round 4: Score:9 Continue!'
'Round 5: Score:7 Failed!'
代码思路:
关于rand():
首先我们须了解:
①rand()函数包含在<stdlib.h>中。
②rand()函数定义:int rand(void);
②rand()函数产生的随机数范围为0-0x7fff,即0-32767。(事实上根据编译器的不同范围也会不同,但都为0~RAND_MAX )
注意:虽然rand()可以产生随机数,但每次的随机数值都是一样的,这个时候我们就需要srand()设置随机函数种子来使每一次的随机数都不同
关于srand():
首先我们须了解:
①srand()函数包含在<stdlib.h>中。
②srand()函数定义 : void srand (unsigned int seed);
③在调用rand()函数产生随机数前,必须先利用srand()设好随机数种子(seed), 如果未设随机数种子, rand()在调用时会自动设随机数种子为1。
本题的随机函数种子已经给出:参数
randSeed
为随机数种子。所以我们可以直接用srand(randSeed
)表示。而抛骰子游戏要求每一次的随机数在1~6之间,所以我们可以用rand()%6+1实现。在实现完随机数的设定后,后面的代码只需要根据题意编程即可
代码表示:
#include<time.h>
#include<stdio.h>
#include<stdlib.h>
/***在下面Begin至End间,按原型 void diceGame(int randSeed) 定义函数***/
/********** Begin **********/
void diceGame(int randSeed)
{
srand(randSeed);
int x, y, z, i;
x = rand();
x = x % 6 + 1;
y = rand();
y = y % 6 + 1;
z = x + y;
if (z == 7 || z == 11) printf("Round 1: Score:%d Success!", z);
else if (z == 2 || z == 3 || z == 12) printf("Round 1: Score:%d Failed!", z);
else
{
printf("Round 1: Score:%d Continue!\n", z);
printf("Next rounds: Score %d:Success, Score 7:Failed, others:Continue\n", z);
int a, b, c;
for (i = 2; i < 10; i++)
{
a = rand();
a = a % 6 + 1;
b = rand();
b = b % 6 + 1;
c = a + b;
if (c != z && c != 7) printf("Round %d: Score:%d Continue!\n", i, c);
else if (c == z)
{
printf("Round %d: Score:%d Success!\n", i, c);
break;
}
else if (c == 7)
{
printf("Round %d: Score:7 Failed!", i);
break;
}
}
}
}
第2关:冰雹数:
题目:
本关任务(习题
5.11
):n0
是一个给定的正整数,对于i=0,1,2...
,定义:(1)若
ni
是偶数,则ni+1=ni/2
;(2)若
ni
是奇数,则ni+1=3ni+1
;(3)若
ni
是1
,则序列结束。用该方法产生的数称为冰雹
(hailstone)
。编写产生一些冰雹的程序,程序应该用函数
void hailstone(int n)
;计算冰雹并显示由n
产生的序列测试输入:
77
//输入为给定的整数预期输出:(每个冰雹数占
5
位宽,一行输出6
个数)
input a number:Hailstone generated by 77:
77 232 116 58 29 88
44 22 11 34 17 52
26 13 40 20 10 5
16 8 4 2 1
Number of hailstone generated:23
代码思路:
本题我的思路是先用while循环将冰雹数全部列出,当n==1时break跳出循环,每行6个数只需要用for循环即可,换行的话在每次for循环以后输出\n即可,唯一的难点就是当1是第六个数时for循环会自动跳出,导致1可能无法打印出来,所以我在for循环后面又加了两层if语句来避免这种情况。
代码表示:
#include <stdio.h>
//请根据主程序流程,补全此函数
//冰雹产生并输出函数
//注意:输出每个冰雹数时,请按5位对齐输出
void hailstone(int n)
{
printf("Hailstone generated by %d:\n", n);
/********** Begin **********/
int count = 0;
while (n)
{
int i;
for (i = 0; i < 6; i++)
{
if (n == 1)
break;
printf("%5d", n);
if (n % 2 == 0)
n = n / 2;
else
n = 3 * n + 1;
count++;
}
if (n == 1)
{
if (i == 6)
{
printf("\n");
}
printf("%5d\n", n);
count++;
break;
}
printf("\n");
}
printf("Number of hailstone generated:%d", count);
}
第3关:输出整数中指定位数的数值 :
题目:
本关任务:输入整数
n
和k
,输出n
中从右端开始的第k
个数字的值(k
从1
开始)。将求
n
中右端第k
个数字定义成函数digit(n,k)
,如果k
超过了n
的位数,则函数返回-1
;否则返回n
中第k
个数字。例如:
digit(345876,4)=5
digit(345,4)=-1
。测试输入:
345876 4
//输入的是n = 345876 , k = 4
预期输出:
5
代码思路:
这题我的思路就是用while循环得出n的位数,然后与k比较,如果k>b就返回-1,k<b就打印出对应的值,这里有一个细节就是当n在0~9之间时需要额外考虑,因为0~9之间while循环无法得出其位数(困惑了我好久o(╥﹏╥)o)。
代码表示:
#include <stdio.h>
#include<string.h>
//请根据step3_main.cpp中的主函数流程,补全此函数
int digit(long n, int k)
{
/********** Begin **********/
int b = 0;
int a = 0;
int c = n;
if (n < 10 & n >= 0 & k == 1)
{
return n;
}
while (c)
{
c = c / 10;
b++;
}
if (k > b)
return -1;
else
{
for (int i = 1; i < k; i++)
{
n = n / 10;
}
}
a = n % 10;
return a;
/********** End **********/
}
第4关:递归实现标准库函数strlen(s)
题目:
本关任务:用递归实现标准库函数
strlen(s)
。测试输入:
husterNB!
预期输出:
9
代码思路:
题目要求我们用递归的思路,我们可以用if语句判断s的首元素地址是否存在,存在就b++,然后通过递归判断第二个元素是否存在,存在就继续加一,一直循环下去,直到字符串的位置不存在时,表明该字符串已经结束,则返回之前递归循环得到的b的值(这里的b我设的是全局变量,防止在递归过程中b的值一直被刷新)
代码表示:
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
//请根据step4_main.c中主函数流程
//使用递归的方法补全此函数
int b = 0;
int mystrlen(char *s)
{
/********** Begin **********/
if(*s)
{
b++;
mystrlen(s+1);
}
else
return b;
/********** End **********/
}
第5关:递归实现逆序 :
题目:
本关任务:将输入的一行字符逆序输出。
例如,输入
string
,则输出gnirts
。将逆序输出用递归函数实现。测试输入:
string
预期输出:
gnirts
代码思路:
这题我使用scanf(“%c”)的形式,每次读取一个字符,然后用if判断该字符串是否结束,然后利用递归将字符串从后往前一次打印出来。
代码表示:
#include<stdio.h>
void myrever(void)
{
/********** Begin **********/
char a;
scanf("%c", &a);
if (a != '\n')
{
myrever();
printf("%c", a);
}
/********** End **********/
}
第6关:最大公约数
题目:
本关任务:用辗转相除法计算两个数的最大公约数,要求用递归函数实现求最大公约数。
测试输入:
24 16
预期输出:
24 16
16 8
8 0
8
代码思路:
辗转相除法法求最大公约数:
给定两个数,求这两个数的最大公约数欧几里得算法又称辗转相除法,是指用于计算两个非负整数a,b的最大公约数。应用领域有数学和计算机两个方面。计算公式gcd(a,b) = gcd(b,a mod b)。
例如:假如需要求 100 和18 两个正整数的最大公约数,用欧几里得算法,是这样进行的:
100 / 18 = 5 (余 10)
18 / 10= 1(余8)
10 / 8 = 1(余2)
8 / 2 = 4 (余0)
至此,最大公约数为2
以除数和余数反复做除法运算,当余数为 0 时,取当前算式除数为最大公约数,所以就得出了 100 和 18 的最大公约数2。关于最大公因数求法,我在之前博客里有讲到(http://t.csdn.cn/63j7w),至于为什么要加入新的变量i,并用静态变量修饰,是为了打印出第一次计算时的初始数24,16(题目要求打印出每一次的计算过程,我在这方面被困了好久o(╥﹏╥)o)
代码表示:
#include<stdio.h>
/**
按任务要求补全该函数
用递归实现辗转相除法
**/
int gcd(int x, int y)
{
/********** Begin **********/
static int i = 0;
if (i == 0)
{
printf("%d %d\n", x, y);
}
if (y == 0)
{
return x;
}
else
{
int r = x % y;
printf("%d %d\n", y, r);
i++;
return gcd(y, r);
}
/********** End **********/
}