设计一个100以内四则运算的小程序
要求如下
1)在源程序起始的文件头注释块(comment header)中写上必要的信息;
2)定义函数int randN1N2(int N1, int N2),该函数的功能是:生成并返回一个[N1, N2]之间均匀分布的随机整数,其中形参需满足N1 <= N2。
3)定义函数char randOperator( ),该函数没有输入参数,功能是:随机返回 ’+’、 ’-’、 ’*’、 ’/’ 这四个字符的其中一个。要求在该函数内部调用上述randN1N2( )函数来实现。
4)定义函数int randLmt100( ),该函数没有输入参数,功能是生成并返回一个[0, 99]之间均匀分布的随机整数。要求在该函数内部调用上述randN1N2( )函数来实现。
5)定义函数int addLmt100(int num1, int num2),该函数的功能是:
在屏幕上列出一个算式“num1 + num2 = ”,然后接收一个从键盘输入的计算答案answer。若输入的答案正确,则屏幕输出一行赞扬的语句,然后返回值1;若答案错误,则屏幕输出一行鼓励的语句,并给出正确答案,然后返回值0。
6)定义函数int subLmt100(int num1, int num2),该函数的功能是:
在屏幕上列出一个算式“numMax - numMin = ”,其中numMax是num1和num2中较大的一个数,numMin是num1和num2中较小的一个数;然后接收一个从键盘输入的计算答案answer。若输入的答案正确,则屏幕输出一行赞扬的语句,然后返回值1;若答案错误,则屏幕输出一行鼓励的语句,并给出正确答案,然后返回值0。
7)定义函数int mulLmt100(int num1, int num2),该函数的功能是:
在屏幕上列出一个算式“num1 × num2 = ”,然后接收一个从键盘输入的计算答案answer。若输入的答案正确,则屏幕输出一行赞扬的语句,然后返回值1;若答案错误,则屏幕输出一行鼓励的语句,并给出正确答案,然后返回值0。
8)定义函数int divLmt100( ),该函数没有输入参数。其功能是:
①首先调用randLmt100( )函数生成两个随机整数num1和 num2,并判断num1是否可以被num2整除,若不能整除,则再次调用randLmt100( )函数直到重新生成的num1可以被num2整除为止;
②在屏幕上列出一个算式“num1 ÷ num2 = ”,然后接收一个从键盘输入的计算答案answer。若输入的答案正确,则屏幕输出一行赞扬的语句,然后返回值1;若答案错误,则屏幕输出一行鼓励的语句,并给出正确答案,然后返回值0。
9)主函数int main( )可参照附录B给出的参考流程图编写,功能如下:
调用上述定义的函数,在屏幕上循环的随机出一道四则运算题。其中,定义两个整型数组probNum[4] 和ansNum[4],使用这两个数组分别存储在上述游戏循环过程中加、减、乘、除四种类型的题目出现的次数、以及这四种类型的题目被答对的次数。那么在用户不想继续游戏而退出时,可以在屏幕上显示本次游戏中加、减、乘、除四种类型题目出现的次数,以及每一种题被答对的次数。
我的代码如下
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int randN1N2(int N1, int N2)
{
//srand(time(NULL));//初始化随机数种子
//srand((unsigned)clock());
return rand() % (N2 - N1 + 1) + N1;
}
int randLmt()
{
//srand(time(NULL));
return randN1N2(0, 99);
}
char randOperator()
{
int n = randN1N2(1, 4);
switch (n) {
case 1 :
return '+';
case 2:
return '-';
case 3:
return '*';
case 4:
return '/';
default:
return'+';//默认返回+
}
}
```c
int addLmt100(int num1, int num2)
{
int Ans;
printf("%d + %d =", num1, num2);
scanf_s("%d", &Ans);
if (Ans == num1 + num2)
{
printf("\n恭喜你答对了");
return 1;
}
else
{
printf("\n很遗憾答错了,请继续努力\n");
return 0;
}
减法函数
int subLmt100(int num1, int num2)
{
int numMax,numMin,Ans;
if (num1 > num2)
{
numMax = num1;
numMin = num2;
}
else
{
numMax = num2;
numMin = num1;
}
printf("%d - %d =", numMax, numMin);
scanf_s("%d", &Ans);
if (Ans == numMax - numMin)
{
printf("\n恭喜你答对了");
return 1;
}
else
{
printf("\n很遗憾答错了,请继续努力\n");
return 0;
}
}
乘法函数
int mulLmt100(int num1, int num2)
{
int Ans;
printf("%d × %d =", num1, num2);
scanf_s("%d", &Ans);
if (Ans == num1 * num2)
{
printf("\n恭喜你答对了");
return 1;
}
else
{
printf("\n很遗憾答错了,请继续努力\n");
return 0;
}
}
除法函数
```c
int divLmt100()
{
int num1, num2,Ans;
do {
num1 = randLmt();
num2 = randLmt();
} while (num2 == 0 || num1 % num2 != 0);
printf(" %d ÷ %d = ", num1, num2);
scanf_s("%d", &Ans);
if (Ans == num1 / num2)
{
printf("\n恭喜你答对了");
return 1;
}
else
{
printf("\n很遗憾答错了,继续努力\n");
return 0;
}
}
主函数
```c
int main()
{
int probNum[4] = { 0,0,0,0 };
int AnsNum[4] = { 0,0,0,0 };
int sFlag = 1;
int total;
int numa, numb;
char ope,yn,ny;
do {
//srand((unsigned)clock());
numa = randLmt();
srand((unsigned)clock());
numb = randLmt();
ope = randOperator();
switch (ope)
{
case '+':
probNum[0]++;
if (addLmt100(numa, numb))
{
AnsNum[0]++;
printf("\n继续做题吗?");
//fflush(stdin);
int c;
while ((c = getchar()) != '\n' && c != EOF) {} // 清空输入缓冲区
//scanf_s("%c",&ny);
//printf("%c", ny);//判断是否继续做题
ny = getchar();
if (ny == 'y' || ny == 'Y')
sFlag = 1;
else
{
sFlag = 0;
}
}
else
{
printf("继续做题吗?");
fflush(stdin);
yn = getchar(); //判断是否继续做题
if (yn == 'y' || yn == 'Y')
sFlag = 1;
else if (yn == 'N' || yn == 'n')
{
sFlag = 0;
}
}
case '-':
probNum[1]++;
if (subLmt100(numa, numb))
{
AnsNum[1]++;
printf("\n继续做题吗?");
int c;
while ((c = getchar()) != '\n' && c != EOF) {}
//scanf_s("%c", &ny); //判断是否继续做题
ny = getchar();
if (ny == 'y' || ny == 'Y')
sFlag = 1;
else
{
sFlag = 0;
}
}
else
{
printf("继续做题吗?");
fflush(stdin);
yn = getchar(); //判断是否继续做题
if (yn == 'y' || yn == 'Y')
sFlag = 1;
else
{
sFlag = 0;
}
}
case'*':
probNum[2]++;
if (mulLmt100(numa, numb))
{
AnsNum[2]++;
printf("\n继续做题吗?");
//fflush(stdin);
//scanf_s("%c", &ny); //判断是否继续做题
int c;
while ((c = getchar()) != '\n' && c != EOF) {}
ny = getchar();
if (ny == 'y' || ny == 'Y')
sFlag = 1;
else if (ny == 'N' || ny == 'n')
{
sFlag = 0;
}
}
else
{
printf("继续做题吗?");
yn = getchar(); //判断是否继续做题
if (yn == 'y' || yn == 'Y')
sFlag = 1;
else if (yn == 'N' || yn == 'n')
{
sFlag = 0;
}
}
case '/' :
probNum[3]++;
if (divLmt100())
{
AnsNum[3]++;
printf("\n继续做题吗?");
int c;
while ((c = getchar()) != '\n' && c != EOF) {}
//fflush(stdin);
//scanf_s("%c", &ny);
ny = getchar(); //判断是否继续做题
if (ny == 'y' || ny == 'Y')
sFlag = 1;
else
{
sFlag = 0;
}
}
else
{
printf("继续做题吗?");
yn = getchar(); //判断是否继续做题
if (yn == 'y' || yn == 'Y')
sFlag = 1;
else if (yn == 'N' || yn == 'n')
{
sFlag = 0;
}
}
default:
break;
}
/*printf("继续做吗?");
yn = getchar(); //判断是否继续做题
if (yn == 'y' || yn == 'Y')
sFlag = 1;
else if(yn == 'N' ||yn=='n')
{
sFlag = 0;
}*/
} while (sFlag == 1);
total = probNum[0] + probNum[1] + probNum[2] + probNum[3];
printf("\n总共做了%d道题,%d道加法题,%d道减法题,%d道乘法题,%d道除法题 ", total,probNum[0],probNum[1],probNum[2],probNum[3]);
printf("\n加法题做对了%d道,减法题做了%d道,乘法题做了%d道,除法题做对了%d道题", AnsNum[0], AnsNum[1], AnsNum[2], AnsNum[3]);
return 0;
}
问题:1.我是用的是do while 循环 每次使用do 为什么加减乘产生的随机数2个随机数每次都是相同的?(除法使用的随机数产生函数不同所以不一样)
2.回答正确后,按照要求是输入Y或者y继续回答问题,n或者N拒绝回答问题并结算,可是我输入q的时候加减乘都会继续回答问题,除法则会进入结算页面?我不知道这是什么原因?
在使用switch 函数时,如果某一个case没有break,那么将会在这个条件下顺序执行下去不会在进行case的判断,比如说case“+”,如果执行完没有break;则会直接执行case“-”case“*”等
——————————————
随机数问题参考GPT回答:
使用clock()函数作为随机数种子,在一次运行程序中生成的随机数是不同的。这是因为clock()函数返回的是程序执行时钟所使用的时间,每次程序的执行时间都是不同的,因此使用clock()函数作为随机数种子可以产生不同的随机数序列。
需要注意的是,clock()函数返回的是程序执行的CPU时间,而不是系统时间。因此,如果程序中存在I/O等阻塞操作,程序的执行时间会受到影响,从而可能会影响随机数的随机性。此外,如果程序的执行时间很短,可能会导致随机数序列不够随机,因此在生成随机数时需要谨慎使用。
总之,使用clock()函数作为随机数种子可以在一次运行程序中生成不同的随机数序列,但需要注意程序的执行时间和随机数的随机性。如果需要更加随机的随机数序列,可以考虑使用其他更加随机的种子,例如时间戳或进程ID等。
1.case后未接break,所以你每次进入加减乘后会进入下一个运算,没有进入下一个循环。
2.
if (ny == 'y' || ny == 'Y')
sFlag = 1;
else
{
sFlag = 0;
}
与
if (yn == 'y' || yn == 'Y')
sFlag = 1;
else if (yn == 'N' || yn == 'n')
{
sFlag = 0;
上一个输入q时会进入else中sFlag = 0;
下一个输入q两个条件都不满足,sFlag不变,为1
我可以为您提供以下优化思路和代码解决方案:
问题1: 产生的两个随机数相同的根本原因在于randN1N2()函数中计算随机数的代码不正确,可以使用C++11中提供的随机数生成器std::mt19937和std::uniform_int_distribution代替rand()函数,具体实现如下:
#include <random>
#include <chrono>
int randN1N2(int N1, int N2) {
static std::mt19937 rng(std::chrono::system_clock::now().time_since_epoch().count());
std::uniform_int_distribution<int> unidist(N1, N2);
return unidist(rng);
}
使用std::mt19937生成器和std::uniform_int_distribution分配器可以保证生成的随机数是均匀分布的,而且避免了rand()函数的线程安全问题。
问题2: 用户输入q后只有除法会进入结算页面是因为您的代码中只对除法的输入进行了处理,可以在addLmt100()、subLmt100()、mulLmt100()函数中加入类似于divLmt100()函数中的处理逻辑,即在用户输入不想回答并结算的时候,break掉循环。
优化后的代码如下:
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <string>
using namespace std;
int randN1N2(int N1, int N2) {
static std::mt19937 rng(std::chrono::system_clock::now().time_since_epoch().count());
std::uniform_int_distribution<int> unidist(N1, N2);
return unidist(rng);
}
char randOperator() {
int op = randN1N2(1, 4);
switch (op) {
case 1: return '+';
case 2: return '-';
case 3: return '*';
case 4: return '/';
default: return '+';
}
}
int randLmt100() {
return randN1N2(0, 99);
}
int addLmt100(int num1, int num2) {
cout << num1 << " + " << num2 << " = " << endl;
int ans;
cin >> ans;
if (ans == num1 + num2) {
cout << "Very good!" << endl;
return true;
} else if (ans == 'q' || ans == 'Q') {
return false;
} else {
cout << "Sorry, the answer is " << num1 + num2 << endl;
return false;
}
}
int subLmt100(int num1, int num2) {
if (num1 < num2) {
swap(num1, num2);
}
cout << num1 << " - " << num2 << " = " << endl;
int ans;
cin >> ans;
if (ans == num1 - num2) {
cout << "Very good!" << endl;
return true;
} else if (ans == 'q' || ans == 'Q') {
return false;
} else {
cout << "Sorry, the answer is " << num1 - num2 << endl;
return false;
}
}
int mulLmt100(int num1, int num2) {
cout << num1 << " * " << num2 << " = " << endl;
int ans;
cin >> ans;
if (ans == num1 * num2) {
cout << "Very good!" << endl;
return true;
} else if (ans == 'q' || ans == 'Q') {
return false;
} else {
cout << "Sorry, the answer is " << num1 * num2 << endl;
return false;
}
}
int divLmt100() {
int num1, num2;
do {
num1 = randLmt100();
num2 = randLmt100();
} while (num2 == 0 || num1 % num2 != 0);
cout << num1 << " / " << num2 << " = " << endl;
int ans;
cin >> ans;
if (ans == num1 / num2) {
cout << "Very good!" << endl;
return true;
} else if (ans == 'q' || ans == 'Q') {
return false;
} else {
cout << "Sorry, the answer is " << num1 / num2 << endl;
return false;
}
}
int main() {
string name;
cout << "Please enter your name: ";
cin >> name;
cout << "Welcome to Math Game, " << name << "!" << endl;
srand(time(0));
int probNum[] = {0, 0, 0, 0};
int ansNum[] = {0, 0, 0, 0};
while (true) {
int num1 = randLmt100();
int num2 = randLmt100();
char op = randOperator();
switch (op) {
case '+': {
probNum[0]++;
if (addLmt100(num1, num2)) {
ansNum[0]++;
break;
} else {
break;
}
}
case '-': {
probNum[1]++;
if (subLmt100(num1, num2)) {
ansNum[1]++;
break;
} else {
break;
}
}
case '*': {
probNum[2]++;
if (mulLmt100(num1, num2)) {
ansNum[2]++;
break;
} else {
break;
}
}
case '/': {
probNum[3]++;
if (divLmt100()) {
ansNum[3]++;
break;
} else {
break;
}
}
default: break;
}
cout << "Do you want to continue? (y/n)" << endl;
char choice;
cin >> choice;
if (choice == 'n' || choice == 'N') {
break;
}
}
cout << "Game over! Here are the results:" << endl;
cout << "Addition: " << ansNum[0] << "/" << probNum[0] << endl;
cout << "Subtraction: " << ansNum[1] << "/" << probNum[1] << endl;
cout << "Multiplication: " << ansNum[2] << "/" << probNum[2] << endl;
cout << "Division: " << ansNum[3] << "/" << probNum[3] << endl;
return 0;
}
以上是我的解决方案,希望对您有所帮助!