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

程序设计题:小学 100 以内正整数加减运算
1 问题描述
设计并实现“小学 100 以内整数加减运算”系统,程序要求如下:
(1)随机出 10 道题,这 10 道题目不能重复,如果是减法运算,要求被减数大于减数。
(2)这些题目,可以选择以下两种方式中的一种给出:
a.选择题,要求随机生成 4 个选项,正确答案包含其中;
b.填空题,可以让用户从键盘输入答案。 (3)用户每次答题,能根据答案计算是否得分,并计入总分。 (4)答题完毕,系统给出总用时。
(5)根据答题情况,能将用户的错误作答题目及答案保存,可以提供用户查看错题功能
2 功能要求
代码要能提供以下几个基本功能。
(1)提供菜单选项,让用户登录,答题。
(2)提供菜单选项,让用户查阅答题情况,答题期间不能查阅。
(3)提供菜单选项,错题再答,如果错题答对了,应从错题集中删除。
(4)提供菜单选项,可以选择生成题目到文本文件,同时生成所对应的答案到相应的
文本文件,以便线下测试。
选做要求: (1)在运算中添加括号,比如 5-(95-93),系统也能正确算出答案。 (2)在菜单选项中,增加帮助功能,提供系统使用说明,模拟答题功能。
3 其他要求
(1)界面美观,交互方便。
(2)注释详细:每个变量都要求有注释说明用途;函数有注释说明功能,对参数、返回值也要以注释的形式说明用途;关键的语句段要求有注释解释。
(3)程序的层次清晰,可读性强。
(4)变量、函数命名符合规范。
(5)如有可能,可使用 MFC 等开发工具,实现彩色或图形操作界面。
4 开发环境
可以选择 TC2.0、TC3.0、VC++6.0 等开发环境,或者与老师讨论,选择自己熟悉的开发工具与平台。

#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 100		//出的题目数字范围 x + y = z  x - y = z  0<=x,y,z <= MAX_NUM


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

/********主菜单*********/
/*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("%d", &choice);//获取选择
	while (choice < 0 || choice>4)//判断输入的选择是否在0--4之间  不是的话重新输入
	{
		printf("请重新输入选项:");
		scanf("%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;//题目类型为选择题
	do
	{
		title[n].opt_num1 = rand() % MAX_NUM;//随机生成操作数1
		title[n].opt_num2 = rand() % MAX_NUM;//随机生成操作数2
		title[n].opt_ch = rand() % 2;//随机生成操作符
		switch (title[n].opt_ch)//根据操作符 生成正确答案等
		{
		case 0://加法的情况
			if (title[n].opt_num1 + title[n].opt_num2 <= MAX_NUM)//确保结果在100以内
			{
				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: 即数组上次测试答题后的长度*/
/*参数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_ch)//输出符号
	{
	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("%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();
	for (i = 0; i < TITLE_NUM; i++)//循环生成题目 回答题目
	{
		Creat_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;//题目类型为填空题
	do
	{
		title[n].opt_num1 = rand() % MAX_NUM;//随机生成操作数1
		title[n].opt_num2 = rand() % MAX_NUM;//随机生成操作数2
		title[n].opt_ch = rand() % 2;//随机生成操作符
		switch (title[n].opt_ch)//根据操作符 生成正确答案等
		{
		case 0://加法的情况
			if (title[n].opt_num1 + title[n].opt_num2 <= MAX_NUM)//确保结果在100以内
			{
				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: 即数组上次测试答题后的长度*/
/*参数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_ch)//输出符号
	{
	case 0:printf("+ "); break;
	case 1:printf("- "); break;
	}
	printf("%d = \n", title[n + i].opt_num2);//输出操作数2
	printf("请输入答案:");
	fflush(stdin);//清空缓冲区
	scanf("%d",&title[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;
	int count = 0;//记录回答正确的数量
	clock_t start, end;
	start = clock();
	for (i = 0; i < TITLE_NUM; i++)//循环生成题目 回答题目
	{
		Creat_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 : 即数组上次测试答题后的长度*/
/*参数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("%d", &choice);
	while (choice < 0 || choice>2)
	{
		printf("请重新输入选项:");
		scanf("%d", &choice);
	}
	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)//选择题
			{
				Get_User_Choice(title, n - TITLE_NUM, i);
			}
			else//填空题
			{
				Get_User_Fill(title, n - TITLE_NUM, 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_ch == 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_ch == 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("%d", &choice);//获取选择
	while (choice < 0 || choice>3)//判断输入的选择是否在0--4之间  不是的话重新输入
	{
		printf("请重新输入选项:");
		scanf("%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;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值