【C语言课程设计】二十以内加减法

程序设计题:小学20以内正整数加减运算

  1. 问题描述

设计并实现“小学20以内整数加减运算"系统,程序要求如下

  • 随机出10道题,这10道题目不能重复。
  • 这些题目,可以选择以下两种方式中的一种给出:
    a.选择题,要求随机生成4个选项,正确答案包含其中;
    b.填空题,可以让用户从键盘输入答案。
  • 用户每次答题,能根据答案计算是否得分,并计入总分。
  • 答题完毕,系统给出总用时。
  • 根据答题情况,能将用户的错误作答题目及答案保存,可以提供用户查看错题功能
  1. 功能要求

代码要能提供以下几个基本功能。

  • 提供菜单选项,让用户登录答题
  • 提供菜单选项,让用户选择
    a.10以内运算,可选加法、减法、三个数加减混合(题目和结果的数值范围为[0,1])
    b.20以内运算,可选不进位加法、进位加法、不退位减法、退位减法、三个数加减混合(题目和结果的数值范围为[0,20])
  • 提供菜单选项,让用户查阅答题情况,答题期间不能查阅
  • 提供菜单选项,错题再答,如果错题答对了,应从错题集中删除。
  • 提供菜单选项,可以选择生成题目到文本文件,同时生成所对应的答案到相应的文本文件,以便线下测试。

参考代码:

#define _CRT_SECURE_NO_WARNINGS  //在VS中使用 避免出现scanf printf不安全的警告

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>

#define TITLE_NUM 10	//每次测试的出题量
//#define MAX_NUM 20		//出的题目数字范围



/*********题目结构体************/
typedef struct _Title
{
	int opt_num1;//操作数1
	int opt_num2;//操作数2
	int opt_num3;//操作数3
	int opt_ch1;//操作符0代表+   1代表-
	int opt_ch2;//操作符0代表+   1代表-
	int style;//0代表选择题     1代表填空题
	int correct_ans;//如果是选择保存的是正确选项 如果是填空保存正确答案
	int user_ans;//记录用户的答案	
	int range, ten_cho, twenty_cho;
	int choice[4];//随机生成的4个答案 不重复 其中一个为正确答案
}Title;

int max_num = 20;	//出的题目数字范围
int range;			//0代表10以内     1代表20以内 
int ten_choice;		//10以内加减法方法
int twenty_choice;	//20以内加减法方法

/********主菜单*********/
/*choice记录用户的选择*/
/*返回值:返回用户的选择*/
int Main_Menu()
{
	int choice;
	system("cls");//清空屏幕输出
	printf("1:登录答题\n");
	printf("2:查阅答题\n");
	printf("3:错题再答\n");
	printf("4:打印试卷\n");
	printf("0:退出系统\n");
	printf("请输入选项:");
	scanf_s("%d", &choice);//获取选择
	while (choice < 0 || choice>4)//判断输入的选择是否在0--4之间  不是的话重新输入
	{
		printf("请重新输入选项:");
		scanf_s("%d", &choice);
	}
	return choice;//返回选择
}

/**********生成选择题*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 已答题的数量,即数组当前长度*/
void Creat_Choice_Title(Title title[], int n)
{
	int i, j;//循环迭代使用
	title[n].style = 0;//题目类型为选择题
	title[n].range = range;
	title[n].ten_cho = ten_choice;
	title[n].twenty_cho = twenty_choice;
	
	do
	{
		title[n].opt_num1 = rand() % max_num;//随机生成操作数1
		title[n].opt_num2 = rand() % max_num;//随机生成操作数2
		if((range == 0 && ten_choice == 1) || twenty_choice == 2)//如果是十以内的加法
			title[n].opt_ch1 = 0;		
		else if((range == 0 && ten_choice == 2) || twenty_choice == 3 || twenty_choice == 4)
			title[n].opt_ch1 = 1;
		else
			title[n].opt_ch1 = rand() % 2;//随机生成操作符
		switch (title[n].opt_ch1)//根据操作符 生成正确答案等
		{
		case 0://加法的情况
			if (title[n].opt_num1 + title[n].opt_num2 <= max_num)//确保结果在10以内
			{
				title[n].correct_ans = title[n].opt_num1 + title[n].opt_num2;//得到正确答案
				for (i = 0; i < 4; i++)//随机生成4个选项
				{
					title[n].choice[i] = rand() % max_num;
					while (title[n].choice[i] == title[n].correct_ans)//确保随机生成的选项与答案不重复
					{
						title[n].choice[i] = rand() % max_num;//重复就重新生成
					}
					for (j = 0; j < i; j++)//确保和之前已经生成的选项不重复
					{
						if (title[n].choice[i] == title[n].choice[j])//重复也重新生成
						{
								i--;
							break;
						}
					}
				}
				title[n].correct_ans = rand() % 4;//随机选择一个选项作为正确答案
				title[n].choice[title[n].correct_ans] = title[n].opt_num1 + title[n].opt_num2;//把答案放在正确选项的位置
				return;
			}
			break;
		case 1://减法的情况
			if (title[n].opt_num1 - title[n].opt_num2 >= 0)//确保答案大于0
			{
				title[n].correct_ans = title[n].opt_num1 - title[n].opt_num2;//获取正确答案
				for (i = 0; i < 4; i++)//随机生成4个选项
				{
					title[n].choice[i] = rand() % max_num;
					while (title[n].choice[i] == title[n].correct_ans)//确保随机生成的选项与答案不重复
					{
						title[n].choice[i] = rand() % max_num;//重复就重新生成
					}
					for (j = 0; j < i; j++)//确保和之前已经生成的选项不重复
					{
						if (title[n].choice[i] == title[n].choice[j])//重复也重新生成
						{
							i--;
							break;
						}
					}
				}
				title[n].correct_ans = rand() % 4;//随机选择一个选项作为正确答案
				title[n].choice[title[n].correct_ans] = title[n].opt_num1 - title[n].opt_num2;//把答案放在正确选项的位置
				return;
			}
			break;
		}
	} while (1);
}

/**********生成选择题(三个数加减混合)*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 已答题的数量,即数组当前长度*/
void Creat_Mix_Choice_Title(Title title[], int n)
{
	int i, j, s;//循环迭代使用
	title[n].style = 0;//题目类型为选择题
	title[n].range = range;
	title[n].ten_cho = ten_choice;
	title[n].twenty_cho = twenty_choice;
	do
	{
		title[n].opt_num1 = rand() % max_num;//随机生成操作数1
		title[n].opt_num2 = rand() % max_num;//随机生成操作数2
		title[n].opt_num3 = rand() % max_num;//随机生成操作数3
		if (rand() % 4 == 0)// 随机选择加减号
		{  
			title[n].opt_ch1 = 0;
			title[n].opt_ch2 = 0;
			s = 1;
		} 
		else if(rand() % 4 == 1)
		{
			title[n].opt_ch1 = 0;
			title[n].opt_ch2 = 1;
			s = 2;
		}
		else if(rand() % 4 == 2)
		{
			title[n].opt_ch1 = 1;
			title[n].opt_ch2 = 0;
			s = 3;
		}
		else
		{
			title[n].opt_ch1 = 1;
			title[n].opt_ch2 = 1;
			s = 4;
		}


		switch (s)//根据操作符 生成正确答案等
		{
		case 1://++的情况
			if (title[n].opt_num1 + title[n].opt_num2 + title[n].opt_num3 <= max_num)//确保结果在max_num以内
			{
				title[n].correct_ans = title[n].opt_num1 + title[n].opt_num2 + title[n].opt_num3;//得到正确答案
				for (i = 0; i < 4; i++)//随机生成4个选项
				{
					title[n].choice[i] = rand() % max_num;
					while (title[n].choice[i] == title[n].correct_ans)//确保随机生成的选项与答案不重复
					{
						title[n].choice[i] = rand() % max_num;//重复就重新生成
					}
					for (j = 0; j < i; j++)//确保和之前已经生成的选项不重复
					{
						if (title[n].choice[i] == title[n].choice[j])//重复也重新生成
						{
								i--;
							break;
						}
					}
				}
				title[n].correct_ans = rand() % 4;//随机选择一个选项作为正确答案
				title[n].choice[title[n].correct_ans] = title[n].opt_num1 + title[n].opt_num2 + title[n].opt_num3;//把答案放在正确选项的位置
				return;
			}
			break;
		case 2://+-的情况
			if (title[n].opt_num1 + title[n].opt_num2 - title[n].opt_num3 >= 0 && title[n].opt_num1 + title[n].opt_num2 - title[n].opt_num3 <= max_num)//确保答案大于0
			{
				title[n].correct_ans = title[n].opt_num1 + title[n].opt_num2 - title[n].opt_num3;//获取正确答案
				for (i = 0; i < 4; i++)//随机生成4个选项
				{
					title[n].choice[i] = rand() % max_num;
					while (title[n].choice[i] == title[n].correct_ans)//确保随机生成的选项与答案不重复
					{
						title[n].choice[i] = rand() % max_num;//重复就重新生成
					}
					for (j = 0; j < i; j++)//确保和之前已经生成的选项不重复
					{
						if (title[n].choice[i] == title[n].choice[j])//重复也重新生成
						{
							i--;
							break;
						}
					}
				}
				title[n].correct_ans = rand() % 4;//随机选择一个选项作为正确答案
				title[n].choice[title[n].correct_ans] = title[n].opt_num1 + title[n].opt_num2 - title[n].opt_num3;//把答案放在正确选项的位置
				return;
			}
			break;
			case 3://-+的情况
				if (title[n].opt_num1 - title[n].opt_num2 + title[n].opt_num3 >= 0 && title[n].opt_num1 - title[n].opt_num2 + title[n].opt_num3 <= max_num)//确保答案大于0
				{
					title[n].correct_ans = title[n].opt_num1 - title[n].opt_num2 + title[n].opt_num3;//获取正确答案
					for (i = 0; i < 4; i++)//随机生成4个选项
					{
						title[n].choice[i] = rand() % max_num;
						while (title[n].choice[i] == title[n].correct_ans)//确保随机生成的选项与答案不重复
						{
							title[n].choice[i] = rand() % max_num;//重复就重新生成
						}
						for (j = 0; j < i; j++)//确保和之前已经生成的选项不重复
						{
							if (title[n].choice[i] == title[n].choice[j])//重复也重新生成
							{
								i--;
								break;
							}
						}
					}
					title[n].correct_ans = rand() % 4;//随机选择一个选项作为正确答案
					title[n].choice[title[n].correct_ans] = title[n].opt_num1 - title[n].opt_num2 + title[n].opt_num3;//把答案放在正确选项的位置
					return;
				}
			case 4://--的情况
				if (title[n].opt_num1 - title[n].opt_num2 - title[n].opt_num3 >= 0 && title[n].opt_num1 - title[n].opt_num2 - title[n].opt_num3 <= max_num)//确保答案大于0
				{
					title[n].correct_ans = title[n].opt_num1 - title[n].opt_num2 - title[n].opt_num3;//获取正确答案
					for (i = 0; i < 4; i++)//随机生成4个选项
					{
						title[n].choice[i] = rand() % max_num;
						while (title[n].choice[i] == title[n].correct_ans)//确保随机生成的选项与答案不重复
						{
							title[n].choice[i] = rand() % max_num;//重复就重新生成
						}
						for (j = 0; j < i; j++)//确保和之前已经生成的选项不重复
						{
							if (title[n].choice[i] == title[n].choice[j])//重复也重新生成
							{
								i--;
								break;
							}
						}
					}
					title[n].correct_ans = rand() % 4;//随机选择一个选项作为正确答案
					title[n].choice[title[n].correct_ans] = title[n].opt_num1 - title[n].opt_num2 - title[n].opt_num3;//把答案放在正确选项的位置
					return;
				}
		}
	} while (1);
}

/**********生成选择题(不进位加法)*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 已答题的数量,即数组当前长度*/
void Creat_Not_Carry_Choice_Title(Title title[], int n)
{
	int i, j;//循环迭代使用
	title[n].style = 0;//题目类型为选择题
	title[n].range = range;
	title[n].ten_cho = ten_choice;
	title[n].twenty_cho = twenty_choice;
	title[n].opt_ch1 = 0;
	do
	{
		title[n].opt_num1 = rand() % max_num;//随机生成操作数1
		if(title[n].opt_num1 >= 10)
			title[n].opt_num2 = rand() % (20 - title[n].opt_num1);
		else
			title[n].opt_num2 = rand() % (10 - title[n].opt_num1 % 10) + 10;//随机生成操作数2

		int result = title[n].opt_num1 + title[n].opt_num2;  // 不进位相加运算
		if(result <= max_num && result >= 0)
		{
			title[n].correct_ans = result;//得到正确答案
			for (i = 0; i < 4; i++)//随机生成4个选项
			{
				title[n].choice[i] = rand() % max_num;
				while (title[n].choice[i] == title[n].correct_ans)//确保随机生成的选项与答案不重复
				{
					title[n].choice[i] = rand() % max_num;//重复就重新生成
				}
				for (j = 0; j < i; j++)//确保和之前已经生成的选项不重复
				{
					if (title[n].choice[i] == title[n].choice[j])//重复也重新生成
					{
							i--;
						break;
					}
				}
			}
			title[n].correct_ans = rand() % 4;//随机选择一个选项作为正确答案
			title[n].choice[title[n].correct_ans] = result;//把答案放在正确选项的位置
			break;
		}		
	} while (1);
}

/**********生成选择题(进位加法)*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 已答题的数量,即数组当前长度*/
void Creat_Carry_Choice_Title(Title title[], int n)
{
	int i, j;//循环迭代使用
	title[n].style = 0;//题目类型为选择题
	title[n].range = range;
	title[n].ten_cho = ten_choice;
	title[n].twenty_cho = twenty_choice;
	title[n].opt_ch1 = 0;
	do
	{
		title[n].opt_num1 = rand() % max_num;//随机生成操作数1
		title[n].opt_num2 = rand() % max_num;//随机生成操作数2
		int carry = (title[n].opt_num1 % 10 + title[n].opt_num2 % 10) / 10;  // 判断是否需要进位
        if (carry == 0) continue;  // 不需要进位则重新生成        
        int result = title[n].opt_num1 + title[n].opt_num2;  // 进位相加运算		
		if(result <= max_num && result >= 0)
		{
			title[n].correct_ans = result;//得到正确答案
			for (i = 0; i < 4; i++)//随机生成4个选项
			{
				title[n].choice[i] = rand() % max_num;
				while (title[n].choice[i] == title[n].correct_ans)//确保随机生成的选项与答案不重复
				{
					title[n].choice[i] = rand() % max_num;//重复就重新生成
				}
				for (j = 0; j < i; j++)//确保和之前已经生成的选项不重复
				{
					if (title[n].choice[i] == title[n].choice[j])//重复也重新生成
					{
							i--;
						break;
					}
				}
			}
			title[n].correct_ans = rand() % 4;//随机选择一个选项作为正确答案
			title[n].choice[title[n].correct_ans] = result;//把答案放在正确选项的位置
			break;
		}		
	} while (1);

}


/**********生成选择题(不退位减法)*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 已答题的数量,即数组当前长度*/
void Creat_Not_Borrow_Choice_Title(Title title[], int n)
{
	int i, j;//循环迭代使用
	title[n].style = 0;//题目类型为选择题
	title[n].range = range;
	title[n].ten_cho = ten_choice;
	title[n].twenty_cho = twenty_choice;
	title[n].opt_ch1 = 1;
	do
	{
		title[n].opt_num1 = rand() % max_num + 1; // 随机生成1-20之间的数
        title[n].opt_num2 = rand() % title[n].opt_num1 + 1; // b必须小于等于a,且不能为0     	
		int result = title[n].opt_num1 - title[n].opt_num2;  // 不退位相减运算
		if(result <= max_num && result >= 0 && (title[n].opt_num1 % 10) >= (title[n].opt_num2 % 10))
		{
			title[n].correct_ans = result;//得到正确答案
			for (i = 0; i < 4; i++)//随机生成4个选项
			{
				title[n].choice[i] = rand() % max_num;
				while (title[n].choice[i] == title[n].correct_ans)//确保随机生成的选项与答案不重复
				{
					title[n].choice[i] = rand() % max_num;//重复就重新生成
				}
				for (j = 0; j < i; j++)//确保和之前已经生成的选项不重复
				{
					if (title[n].choice[i] == title[n].choice[j])//重复也重新生成
					{
							i--;
						break;
					}
				}
			}
			title[n].correct_ans = rand() % 4;//随机选择一个选项作为正确答案
			title[n].choice[title[n].correct_ans] = result;//把答案放在正确选项的位置
			break;
		}		
	} while (1);

}


/**********生成选择题(退位相减)*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 已答题的数量,即数组当前长度*/
void Creat_Borrow_Choice_Title(Title title[], int n)
{
	int i, j;//循环迭代使用
	title[n].style = 0;//题目类型为选择题
	title[n].range = range;
	title[n].ten_cho = ten_choice;
	title[n].twenty_cho = twenty_choice;
	title[n].opt_ch1 = 1;
	do
	{
		title[n].opt_num1 = rand() % max_num + 1; // 随机生成1-20之间的数
        title[n].opt_num2 = rand() % title[n].opt_num1 + 1; // b必须小于等于a,且不能为0     	
		int result = title[n].opt_num1 - title[n].opt_num2;  // 不退位相减运算
		if(result > 9 || (title[n].opt_num1 % 10) >= (title[n].opt_num2 % 10) || result == 0) continue;
		if(result <= max_num && result > 0)
		{
			title[n].correct_ans = result;//得到正确答案
			for (i = 0; i < 4; i++)//随机生成4个选项
			{
				title[n].choice[i] = rand() % max_num;
				while (title[n].choice[i] == title[n].correct_ans)//确保随机生成的选项与答案不重复
				{
					title[n].choice[i] = rand() % max_num;//重复就重新生成
				}
				for (j = 0; j < i; j++)//确保和之前已经生成的选项不重复
				{
					if (title[n].choice[i] == title[n].choice[j])//重复也重新生成
					{
							i--;
						break;
					}
				}
			}
			title[n].correct_ans = rand() % 4;//随机选择一个选项作为正确答案
			title[n].choice[title[n].correct_ans] = result;//把答案放在正确选项的位置
			break;
		}		
	} while (1);

}

/**********选择题获取用户的答案*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 即数组上次测试答题后的长度*/
/*参数2 int i: 当前测试的第i+1题*/
/*返回值:0代表该题答错  1代表回答正确*/
int Get_User_Choice(Title title[], int n, int i)
{
	int j;//用于迭代
	char choice;//获取 用户选择
	system("cls");//清屏
	printf("第%d题: ", i + 1);//输出题号
	printf("%d ", title[n + i].opt_num1);//输出操作数1
	switch (title[n + i].opt_ch1)//输出符号
	{
	case 0:printf("+ "); break;
	case 1:printf("- "); break;
	}
	printf("%d = \n", title[n + i].opt_num2);//输出操作数2
	for (j = 0; j < 4; j++)//打印4个选项
	{
		printf("%c:%d    ", 'A' + j, title[n + i].choice[j]);
	}
	printf("\n");
	printf("请输入选择:");
	fflush(stdin);//清空缓冲区
	scanf_s("%c", &choice);//获取选择
	choice = toupper(choice);//转换成大写
	while (choice < 'A' || choice > 'D')//判断输入数据的范围 不在A--D则重新输入
	{
		printf("请重新输入选择:");
		fflush(stdin);
		scanf("%c", &choice);
		choice = toupper(choice);
	}
	title[n + i].user_ans = choice - 'A';//记录用户的选择
	if (title[n + i].user_ans == title[n + i].correct_ans)//如果答对了
	{
		printf("恭喜你,答对了!\n");
		system("pause");
		return 1;
	}
	printf("答错了,正确答案为:%c!\n", title[n + i].correct_ans + 'A');//如果答错了
	system("pause");
	return 0;
}

/**********选择题获取用户的答案(三个数加减混合)*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 即数组上次测试答题后的长度*/
/*参数2 int i: 当前测试的第i+1题*/
/*返回值:0代表该题答错  1代表回答正确*/
int Get_User_Mix_Choice(Title title[], int n, int i)
{
	int j;//用于迭代
	char choice;//获取 用户选择
	system("cls");//清屏
	printf("第%d题: ", i + 1);//输出题号
	printf("%d ", title[n + i].opt_num1);//输出操作数1
	switch (title[n + i].opt_ch1)//输出符号
	{
	case 0:printf("+ "); break;
	case 1:printf("- "); break;
	}
	printf("%d ", title[n + i].opt_num2);//输出操作数2
	switch (title[n + i].opt_ch2)//输出符号
	{
	case 0:printf("+ "); break;
	case 1:printf("- "); break;
	}
	printf("%d = \n", title[n + i].opt_num3);//输出操作数3
	for (j = 0; j < 4; j++)//打印4个选项
	{
		printf("%c:%d    ", 'A' + j, title[n + i].choice[j]);
	}
	printf("\n");
	printf("请输入选择:");
	fflush(stdin);//清空缓冲区
	scanf_s("%c", &choice);//获取选择
	choice = toupper(choice);//转换成大写
	while (choice < 'A' || choice > 'D')//判断输入数据的范围 不在A--D则重新输入
	{
		printf("请重新输入选择:");
		fflush(stdin);
		scanf("%c", &choice);
		choice = toupper(choice);
	}
	title[n + i].user_ans = choice - 'A';//记录用户的选择
	if (title[n + i].user_ans == title[n + i].correct_ans)//如果答对了
	{
		printf("恭喜你,答对了!\n");
		system("pause");
		return 1;
	}
	printf("答错了,正确答案为:%c!\n", title[n + i].correct_ans + 'A');//如果答错了
	system("pause");
	return 0;
}

/**********用户开始回答选择题*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 即数组上次测试答题后的长度*/
/*返回值:本次答题回答正确的题目数量*/
int Start_Choice(Title title[], int n)
{
	int i;
	int count = 0;//记录回答正确的数量
	clock_t start, end;
	start = clock();
	if(ten_choice == 3 || twenty_choice == 5)//三个数混合
	{
		for (i = 0; i < TITLE_NUM; i++)//循环生成题目 回答题目
		{
			Creat_Mix_Choice_Title(title, n + i);//生成题目
			count += Get_User_Mix_Choice(title, n, i);//回答题目
		}		
	}
	else if(ten_choice == 1 || ten_choice == 2)//两个数的加减法
	{
		for (i = 0; i < TITLE_NUM; i++)//循环生成题目 回答题目
		{
			Creat_Choice_Title(title, n + i);//生成题目
			count += Get_User_Choice(title, n, i);//回答题目
		}
	}
	else if(twenty_choice == 1)//不进位加法
	{
		for (i = 0; i < TITLE_NUM; i++)//循环生成题目 回答题目
		{
			Creat_Not_Carry_Choice_Title(title, n + i);//生成题目
			count += Get_User_Choice(title, n, i);//回答题目
		}
	}
	else if(twenty_choice == 2)//进位加法
	{
		for (i = 0; i < TITLE_NUM; i++)//循环生成题目 回答题目
		{
			Creat_Carry_Choice_Title(title, n + i);//生成题目
			count += Get_User_Choice(title, n, i);//回答题目
		}
	}
	else if(twenty_choice == 3)//不退位减法
	{
		for (i = 0; i < TITLE_NUM; i++)//循环生成题目 回答题目
		{
			Creat_Not_Borrow_Choice_Title(title, n + i);
			count += Get_User_Choice(title, n, i);//回答题目
		}
	}
	else if(twenty_choice == 4)//退位减法
	{
		for (i = 0; i < TITLE_NUM; i++)//循环生成题目 回答题目
		{
			Creat_Borrow_Choice_Title(title, n + i);
			count += Get_User_Choice(title, n, i);//回答题目
		}
	}
	
	
	end = clock();
	printf("总用时:%.2f秒\n", (double)(end - start) / CLOCKS_PER_SEC);
	system("pause");
	return count;//返回回答正确的数量
}

/**********生成填空题*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 已答题的数量,即数组当前长度*/
void Creat_Fill_Title(Title title[], int n)
{
	title[n].style = 1;//题目类型为填空题
	title[n].range = range;
	title[n].ten_cho = ten_choice;
	title[n].twenty_cho = twenty_choice;
	do
	{
		title[n].opt_num1 = rand() % max_num;//随机生成操作数1
		title[n].opt_num2 = rand() % max_num;//随机生成操作数2
		
		if((range == 0 && ten_choice == 1) || twenty_choice == 2)
			title[n].opt_ch1 = 0;		
		else if((range == 0 && ten_choice == 2) || twenty_choice == 3 || twenty_choice == 4)
			title[n].opt_ch1 = 1;
		else
			title[n].opt_ch1 = rand() % 2;//随机生成操作符
		switch (title[n].opt_ch1)//根据操作符 生成正确答案等
		{
		case 0://加法的情况
			if (title[n].opt_num1 + title[n].opt_num2 <= max_num)//确保结果在max_num以内
			{
				title[n].correct_ans = title[n].opt_num1 + title[n].opt_num2;//得到正确答案
				return;
			}
			break;
		case 1://减法的情况
			if (title[n].opt_num1 - title[n].opt_num2 >= 0)//确保答案大于0
			{
				title[n].correct_ans = title[n].opt_num1 - title[n].opt_num2;//获取正确答案
				return;
			}
			break;
		}
	} while (1);
}

/**********生成填空题(三个数混合)*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 已答题的数量,即数组当前长度*/
void Creat_Mix_Fill_Title(Title title[], int n)
{
	int s;
	title[n].style = 1;//题目类型为填空题
	title[n].range = range;
	title[n].ten_cho = ten_choice;
	title[n].twenty_cho = twenty_choice;
	do
	{
		title[n].opt_num1 = rand() % max_num;//随机生成操作数1
		title[n].opt_num2 = rand() % max_num;//随机生成操作数2
		title[n].opt_num3 = rand() % max_num;//随机生成操作数3
		//title[n].opt_ch1 = rand() % 2;//随机生成操作符
		if (rand() % 4 == 0)// 随机选择加减号
		{  
			title[n].opt_ch1 = 0;
			title[n].opt_ch2 = 0;
			s = 1;
		} 
		else if(rand() % 4 == 1)
		{
			title[n].opt_ch1 = 0;
			title[n].opt_ch2 = 1;
			s = 2;
		}
		else if(rand() % 4 == 2)
		{
			title[n].opt_ch1 = 1;
			title[n].opt_ch2 = 0;
			s = 3;
		}
		else
		{
			title[n].opt_ch1 = 1;
			title[n].opt_ch2 = 1;
			s = 4;
		}
		switch (s)//根据操作符 生成正确答案等
		{
		case 1://++的情况
			if (title[n].opt_num1 + title[n].opt_num2 + title[n].opt_num3 <= max_num)//确保结果在max_num以内
			{
				title[n].correct_ans = title[n].opt_num1 + title[n].opt_num2 + title[n].opt_num3;//得到正确答案				
				return;
			}
			break;
		case 2://+-的情况
			if (title[n].opt_num1 + title[n].opt_num2 - title[n].opt_num3 >= 0 && title[n].opt_num1 + title[n].opt_num2 - title[n].opt_num3 <= max_num)//确保答案大于0
			{
				title[n].correct_ans = title[n].opt_num1 + title[n].opt_num2 - title[n].opt_num3;//获取正确答案	
				return;
			}
			break;
		case 3://-+的情况
			if (title[n].opt_num1 - title[n].opt_num2 + title[n].opt_num3 >= 0 && title[n].opt_num1 - title[n].opt_num2 + title[n].opt_num3 <= max_num)//确保答案大于0
			{
				title[n].correct_ans = title[n].opt_num1 - title[n].opt_num2 + title[n].opt_num3;//获取正确答案
				return;
			}
			break;
		case 4://--的情况
			if (title[n].opt_num1 - title[n].opt_num2 - title[n].opt_num3 >= 0 && title[n].opt_num1 - title[n].opt_num2 - title[n].opt_num3 <= max_num)//确保答案大于0
			{
				title[n].correct_ans = title[n].opt_num1 - title[n].opt_num2 - title[n].opt_num3;//获取正确答案
				return;
			}
			break;
		}
	} while (1);
}

/**********生成填空题(不进位加法)*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 已答题的数量,即数组当前长度*/
void Creat_Not_Carry_Fill_Title(Title title[], int n)
{
	title[n].style = 1;//题目类型为填空题
	title[n].range = range;
	title[n].ten_cho = ten_choice;
	title[n].twenty_cho = twenty_choice;
	title[n].opt_ch1 = 0;
	do
	{
		title[n].opt_num1 = rand() % max_num;//随机生成操作数1
		if(title[n].opt_num1 >= 10)
			title[n].opt_num2 = rand() % (20 - title[n].opt_num1);
		else
			title[n].opt_num2 = rand() % (10 - title[n].opt_num1 % 10) + 10;//随机生成操作数2
		int result = title[n].opt_num1 + title[n].opt_num2;  // 不进位相加运算
		if(result <= max_num && result >= 0)
		{
			title[n].correct_ans = result;//得到正确答案
			break;
		}		
	} while (1);
}

/**********生成填空题(进位加法)*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 已答题的数量,即数组当前长度*/
void Creat_Carry_Fill_Title(Title title[], int n)
{
	title[n].style = 1;//题目类型为填空题
	title[n].range = range;
	title[n].ten_cho = ten_choice;
	title[n].twenty_cho = twenty_choice;
	do
	{
		title[n].opt_num1 = rand() % max_num;//随机生成操作数1
		title[n].opt_num2 = rand() % max_num;//随机生成操作数2
		int carry = (title[n].opt_num1 % 10 + title[n].opt_num2 % 10) / 10;  // 判断是否需要进位
        if (carry == 0) continue;  // 不需要进位则重新生成        	
		int result = title[n].opt_num1 + title[n].opt_num2;  // 进位相加运算
		if(result <= max_num && result >= 0)
		{
			title[n].correct_ans = result;//得到正确答案
			break;
		}		
	} while (1);
}

/**********生成填空题(不退位减法)*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 已答题的数量,即数组当前长度*/
void Creat_Not_Borrow_Fill_Title(Title title[], int n)
{
	title[n].style = 1;//题目类型为填空题
	title[n].range = range;
	title[n].ten_cho = ten_choice;
	title[n].twenty_cho = twenty_choice;
	title[n].opt_ch1 = 1;
	do
	{
		title[n].opt_num1 = rand() % max_num + 1; // 随机生成1-20之间的数
        title[n].opt_num2 = rand() % title[n].opt_num1 + 1; // b必须小于等于a,且不能为0     	
		int result = title[n].opt_num1 - title[n].opt_num2;  // 不退位相减运算
		if(result <= max_num && result >= 0 && (title[n].opt_num1 % 10) >= (title[n].opt_num2 % 10))
		{
			title[n].correct_ans = result;//得到正确答案
			break;
		}		
	} while (1);
}

/**********生成填空题(退位减法)*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 已答题的数量,即数组当前长度*/
void Creat_Borrow_Fill_Title(Title title[], int n)
{
	title[n].style = 1;//题目类型为填空题
	title[n].range = range;
	title[n].ten_cho = ten_choice;
	title[n].twenty_cho = twenty_choice;
	title[n].opt_ch1 = 1;
	do
	{
		title[n].opt_num1 = rand() % max_num + 1; // 随机生成1-20之间的数
        title[n].opt_num2 = rand() % title[n].opt_num1 + 1; // b必须小于等于a,且不能为0     	
		int result = title[n].opt_num1 - title[n].opt_num2;  // 不退位相减运算
		if(result > 9 || (title[n].opt_num1 % 10) >= (title[n].opt_num2 % 10) || result == 0) continue;
		if(result <= max_num && result > 0)
		{
			title[n].correct_ans = result;//得到正确答案
			break;
		}		
	} while (1);
}

/**********填空题获取用户的答案*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 即数组上次测试答题后的长度*/
/*参数2 int i: 当前测试的第i+1题*/
/*返回值:0代表该题答错  1代表回答正确*/
int Get_User_Fill(Title title[], int n, int i)
{
	system("cls");//清屏
	printf("第%d题: ", i + 1);//输出题号
	printf("%d ", title[n + i].opt_num1);//输出操作数1
	switch (title[n + i].opt_ch1)//输出符号
	{
	case 0:printf("+ "); break;
	case 1:printf("- "); break;
	}
	printf("%d = \n", title[n + i].opt_num2);//输出操作数2
	printf("请输入答案:");
	fflush(stdin);//清空缓冲区
	scanf_s("%d", &title[n + i].user_ans);
	if (title[n + i].user_ans == title[n + i].correct_ans)//如果答对了
	{
		printf("恭喜你,答对了!\n");
		system("pause");
		return 1;
	}
	printf("答错了,正确答案为:%d!\n", title[n + i].correct_ans);//如果答错了
	system("pause");
	return 0;
}

/**********填空题获取用户的答案(三个数混合)*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 即数组上次测试答题后的长度*/
/*参数2 int i: 当前测试的第i+1题*/
/*返回值:0代表该题答错  1代表回答正确*/
int Get_User_Mix_Fill(Title title[], int n, int i)
{
	system("cls");//清屏
	printf("第%d题: ", i + 1);//输出题号
	printf("%d ", title[n + i].opt_num1);//输出操作数1
	switch (title[n + i].opt_ch1)//输出符号
	{
	case 0:printf("+ "); break;
	case 1:printf("- "); break;
	}
	printf("%d ", title[n + i].opt_num2);//输出操作数2
	switch (title[n + i].opt_ch2)//输出符号
	{
	case 0:printf("+ "); break;
	case 1:printf("- "); break;
	}
	printf("%d = \n", title[n + i].opt_num3);//输出操作数3
	printf("请输入答案:");
	fflush(stdin);//清空缓冲区
	scanf_s("%d", &title[n + i].user_ans);
	if (title[n + i].user_ans == title[n + i].correct_ans)//如果答对了
	{
		printf("恭喜你,答对了!\n");
		system("pause");
		return 1;
	}
	printf("答错了,正确答案为:%d!\n", title[n + i].correct_ans);//如果答错了
	system("pause");
	return 0;
}

/**********用户开始回答填空题*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n: 即数组上次测试答题后的长度*/
/*返回值:本次答题回答正确的题目数量*/
int Start_Fill(Title title[], int n)
{
	int i = 0;
	int count = 0;//记录回答正确的数量
	clock_t start, end;
	start = clock();
	if(ten_choice == 3 || twenty_choice == 5)//三个数混合
	{
		for (i = 0; i < TITLE_NUM; i++)//循环生成题目 回答题目
		{
			Creat_Mix_Fill_Title(title, n + i);//生成题目
			count += Get_User_Mix_Fill(title, n, i);//回答题目
		}
	}
	else if(ten_choice == 1 || ten_choice == 2)//两个数的加减法
	{
		for (i = 0; i < TITLE_NUM; i++)//循环生成题目 回答题目
		{
			Creat_Fill_Title(title, n + i);//生成题目
			count += Get_User_Fill(title, n, i);//回答题目
		}
	}
	else if(twenty_choice == 1)//不进位加法
	{
		for (i = 0; i < TITLE_NUM; i++)//循环生成题目 回答题目
		{
			Creat_Not_Carry_Fill_Title(title, n + i);//生成题目
			count += Get_User_Fill(title, n, i);//回答题目
		}		
	}
	else if(twenty_choice == 2)//进位加法
	{
		for (i = 0; i < TITLE_NUM; i++)//循环生成题目 回答题目
		{
			Creat_Carry_Fill_Title(title, n + i);//生成题目
			count += Get_User_Fill(title, n, i);//回答题目
		}
	}
	else if(twenty_choice == 3)//不退位减法
	{
		for (i = 0; i < TITLE_NUM; i++)//循环生成题目 回答题目
		{
			Creat_Not_Borrow_Fill_Title(title, n + i);//生成题目
			count += Get_User_Fill(title, n, i);//回答题目
		}
	}
	else if(twenty_choice == 4)//退位减法
	{
		for (i = 0; i < TITLE_NUM; i++)//循环生成题目 回答题目
		{
			Creat_Borrow_Fill_Title(title, n + i);//生成题目
			count += Get_User_Fill(title, n, i);//回答题目
		}
	}
	
	end = clock();
	printf("总用时:%.2f秒\n", (double)(end - start) / CLOCKS_PER_SEC);
	system("pause");
	return count;//返回回答正确的数量
}

/**********选择计算方法的菜单*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int*n : 即数组上次测试答题后的长度*/
int Style_Menu(Title title[], int n)
{	
	int choice;
	system("cls");
	if(range == 0)
	{
		printf("1:加法\n");
		printf("2:减法\n");
		printf("3:三个数加减混合\n");
		printf("0:返回\n");
		printf("请输入选项:");
		scanf_s("%d", &choice);
		while (choice < 0 || choice > 3)
		{
			printf("请重新输入选项:");
			scanf_s("%d", &choice);
		}
		ten_choice = choice;			
	}
	else if(range == 1)
	{
		printf("1:不进位加法\n");
		printf("2:进位加法\n");
		printf("3:不退位减法\n");
		printf("4:退位减法\n");
		printf("5:三个数加减混合\n");
		printf("0:返回\n");
		printf("请输入选项:");
		scanf_s("%d", &choice);
		while (choice < 0 || choice > 5)
		{
			printf("请重新输入选项:");
			scanf_s("%d", &choice);
		}
		twenty_choice = choice;
	}
	if(choice == 0) return 0;
	else return 1;
}


/**********选择答题范围的菜单*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int*n : 即数组上次测试答题后的长度*/
int Range_Menu(Title title[], int n)
{
	int choice;
	system("cls");
	printf("1:10以内运算\n");
	printf("2:20以内运算\n");
	printf("0:返回\n");
	printf("请输入选项:");
	scanf_s("%d", &choice);
	if(choice == 0) return 0;
	while (choice < 0 || choice > 2)
	{
		printf("请重新输入选项:");
		scanf_s("%d", &choice);
	}
	switch(choice)
	{
	case 1: range = 0;
			max_num = 10;			
			break;
	case 2: range = 1;
			max_num = 20;
			break;
	}
	if(Style_Menu(title, n) == 0) return 0;
	return 1;
}

/**********选择答题方式的菜单*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int*n : 即数组上次测试答题后的长度*/
/*参数2 int*all : 即数组上次测试答题后回答正确的长度*/
/*参数3 int*last : 本次答题回答正确的题量*/
void Start_Menu(Title title[], int* n, int* all, int* last)
{
	int choice;
	system("cls");
	printf("1:选择题\n");
	printf("2:填空题\n");
	printf("0:返回\n");
	printf("请输入选项:");
	scanf_s("%d", &choice);
	while (choice < 0 || choice>2)
	{
		printf("请重新输入选项:");
		scanf_s("%d", &choice);
	}
	if(choice == 0) return;
	if(Range_Menu(title, *n) == 0) return;	//选择答题类型
	switch (choice)//根据选项 进入选择题或填空题
	{
	case 1: *last = Start_Choice(title, *n); *all += *last; *n += TITLE_NUM;  break;
	case 2: *last = Start_Fill(title, *n); *all += *last; *n += TITLE_NUM; break;
	}
}

/**********选择答题方式的菜单*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n : 即数组上次测试答题后的长度*/
/*参数2 int all : 即数组上次测试答题后回答正确的长度*/
/*参数3 int last : 本次答题回答正确的题量*/
void Get_State(Title title[], int n, int all, int last)
{
	int i;
	int count = 0;//记录错题数量
	system("cls");
	printf("当前总共做:%4d题\n", n);
	printf("当前共做对:%4d题\n", all);
	printf("上次共做对:%4d题\n", last);
	for (i = 0; i < n; i++)
	{
		if (title[i].user_ans != title[i].correct_ans)
			count++;
	}
	printf("总错题剩余:%4d题\n", count);
	system("pause");
}

/**********选择答题方式的菜单*********/
/*参数1 Title title[]:已经答过的题目数组,记录新生成的题目*/
/*参数2 int n : 即数组上次测试答题后的长度*/
void Test_Again(Title title[], int n)
{
	int i, flag = 0;
	system("cls");
	if (n == 0)
	{
		printf("当前没有错题\n");
		system("pause");
		return;
	}
	for (i = n - TITLE_NUM; i < n; i++)//遍历前面一次的错题
	{
		if (title[i].correct_ans != title[i].user_ans)//如果该题是错题
		{
			flag = 1;
			if (title[i].style == 0)//选择题
			{
				if(title[i].ten_cho == 3 || title[i].twenty_cho == 5)//如果是三个数混合相加
				{
					Get_User_Mix_Choice(title, 0, i);
				}
				else
					Get_User_Choice(title, 0, i);
			}
			else//填空题
			{
				if(title[i].ten_cho == 3 || title[i].twenty_cho == 5)//如果是三个数混合相加
				{
					Get_User_Mix_Fill(title,0, i);
				}
				else
					Get_User_Fill(title, 0, i);
			}
		}
	}
	if (!flag)
	{
		printf("当前没有错题\n");
	}
	system("pause");
}

void Write2Paper_Choice(Title title[], int n, FILE* fp1, FILE* fp2)
{
	int i;
	char ch;
	for (i = 0; i < n; i++)
	{
		if (title[i].opt_ch1 == 0) ch = '+';
		else ch = '-';
		fprintf(fp1, "第%d题: %d %c %d = \n", i + 1, title[i].opt_num1, ch, title[i].opt_num2);
		fprintf(fp2, "第%d题: %d %c %d = %c\n", i + 1, title[i].opt_num1, ch, title[i].opt_num2, title[i].correct_ans + 'A');
		fprintf(fp1, "A:%d  B:%d  C:%d  D:%d\n\n", title[i].choice[0], title[i].choice[1], title[i].choice[2], title[i].choice[3]);
		fprintf(fp2, "A:%d  B:%d  C:%d  D:%d\n\n", title[i].choice[0], title[i].choice[1], title[i].choice[2], title[i].choice[3]);
	}
}

void Write2Paper_Fill(Title title[], int n, FILE* fp1, FILE* fp2)
{
	int i;
	char ch;
	for (i = 0; i < n; i++)
	{
		if (title[i].opt_ch1 == 0) ch = '+';
		else ch = '-';
		fprintf(fp1, "第%d题: %d %c %d = \n", i + 1, title[i].opt_num1, ch, title[i].opt_num2);
		fprintf(fp2, "第%d题: %d %c %d = %d\n", i + 1, title[i].opt_num1, ch, title[i].opt_num2, title[i].correct_ans);
	}
}

/********生成试卷菜单*********/
void Print_Paper_Menu()
{
	int choice, i, j;
	FILE* fp1, * fp2;
	fp1 = fopen("paper.txt", "w+");//保存试卷
	fp2 = fopen("ans.txt", "w+");//保存答案
	Title title[TITLE_NUM];
	system("cls");//清空屏幕输出
	printf("1:生成选择题\n");
	printf("2:生成填空题\n");
	printf("3:混合生成\n");
	printf("0:返回\n");
	printf("请输入选项:");
	scanf_s("%d", &choice);//获取选择
	while (choice < 0 || choice>3)//判断输入的选择是否在0--4之间  不是的话重新输入
	{
		printf("请重新输入选项:");
		scanf_s("%d", &choice);
	}
	switch (choice)
	{
	case 1:
		for (i = 0; i < TITLE_NUM; i++)//循环生成题目 回答题目
		{
			Creat_Choice_Title(title, i);//生成题目
		}
		Write2Paper_Choice(title, TITLE_NUM, fp1, fp2);
		break;
	case 2:
		for (i = 0; i < TITLE_NUM; i++)//循环生成题目 回答题目
		{
			Creat_Fill_Title(title, i);//生成题目
		}
		Write2Paper_Fill(title, TITLE_NUM, fp1, fp2);
		break;
	case 3:
		for (i = 0; i < TITLE_NUM / 2; i++)//循环生成题目 回答题目
		{
			Creat_Choice_Title(title, i);//生成题目
		}
		Write2Paper_Choice(title, TITLE_NUM / 2, fp1, fp2);
		j = i;
		for (; i < TITLE_NUM; i++)//循环生成题目 回答题目
		{
			Creat_Fill_Title(title, i);//生成题目
		}
		Write2Paper_Fill(title + j, TITLE_NUM - TITLE_NUM / 2, fp1, fp2);
		break;
	}
	if (choice != 0)
	{
		printf("试卷及答案打印成功!请打开文件查看!\n");
		system("pause");
	}
	fclose(fp1);
	fclose(fp2);
}

/*将所有数据写入到文件*/
void Save_File(Title title[], int title_count, int correct_count_all, int correct_count_last)
{
	FILE* fp = fopen("data.dat", "w+");
	if (fp == NULL) return;

	fprintf(fp, "%d %d %d\n", title_count, correct_count_all, correct_count_last);
	fwrite(title, sizeof(Title), title_count, fp);
	fclose(fp);
}

/*将所有数据写入到文件*/
void Load_File(Title title[], int* title_count, int* correct_count_all, int* correct_count_last)
{
	FILE* fp = fopen("data.dat", "r+");
	if (fp == NULL) return;

	if (fscanf(fp, "%d %d %d\n", title_count, correct_count_all, correct_count_last) != 3)
	{
		*title_count = 0;
		*correct_count_all = 0;
		*correct_count_last = 0;
		fclose(fp);
	}
	fread(title, sizeof(Title), *title_count, fp);
	fclose(fp);
}

/*********主函数***********/
int main()
{
	int choice;
	Title title[1000];//题目数组
	int title_count = 0;//总题目长度
	int correct_count_all = 0;//总正确
	int correct_count_last = 0;//上一次正确
	Load_File(title, &title_count, &correct_count_all, &correct_count_last);
	srand(time(NULL));//初始化随机数种子
	do
	{
		choice = Main_Menu();
		switch (choice)
		{
		case 1:Start_Menu(title, &title_count, &correct_count_all, &correct_count_last); break;
		case 2:Get_State(title, title_count, correct_count_all, correct_count_last); break;
		case 3:Test_Again(title, title_count); break;
		case 4:Print_Paper_Menu(); break;
		}
	} while (choice != 0);
	Save_File(title, title_count, correct_count_all, correct_count_last);
	return 0;
}
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

为梦而生~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值