(创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹)
目录
第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
预期输出:
1.'Round 1: Score:8 Continue!'
2.'Next rounds: Score 8:Success, Score 7:Failed, others:Continue'
3.'Round 2: Score:4 Continue!'
4.'Round 3: Score:6 Continue!'
5.'Round 4: Score:9 Continue!'
6.'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 **********/ }