计算机辅助教学(CAI)软件开发:教小学生学英语。
目录
1 课程目的
通过本学习课程更进一步理解C++的基础知识和面向对象的思想。
训练用系统的观点和软件开发一般规范进行软件开发,并在此过程中培养严谨的科学态度和良好的工作作风。
初步掌握软件开发过程的问题分析、系统设计、程序编码、测试等基本方法和技能。
熟练掌握C++中类及模板在程序中的应用,并熟练了解类中函数的调用。
进一步提高上机动手能力,培养使用计算机解决实际问题的能力,为后继课程和毕业设计打下扎实的基础
2 课题题目
计算机辅助教学(CAI)软件开发:教小学生学英语。
3 设计要求
3.1 功能:
屏幕上随机出现一个汉语单词,英语单词,汉语词组,英语词组或一短 句提示小学生给出相应答案,
答错了要提示要求重新输入,直到答对为止。
要统计给分,且累计,够一定分数后可进级,即从单词到词组,从 词组到短句。同样,也可降级。
起步阶段可各选 30 个,软件可扩充,即 扩大词库的容量。
(rand(),#include 结构体、文件或数组)
3.2 要求:
1、用 C++语言实现程序设计;
2、利用结构体数组实现信息的数据结构设计;
3、系统的各个功能模块要求用函数的形式实现;
4、界面友好(良好的人机交互),程序加必要的注释。
4 总体设计
设计分为两个主要的模块:管理员模块和学生端学习模块
4.1 管理员模块
主要负责:词汇的添加、修改、查找、删除,查看词库
4.2 学生端学习模块
主要是:答题
5 详细设计
5.1 管理员模块
5.1.1 密码登录
首次登录密码默认为空,所以直接进入管理界面。
进入管理界面后通过修改密码的来设置管理员的密码,从而进行管理员权限的操作。
为了能使密码下次登录有效就不可以写在磁盘中,需要写在文件或者数据库中,实现密码的读写。
由于时间有限,经小组讨论,本程序采用文件存储词汇。
定义一个文件存account.txt储密码
#define FILENAME3 "account.txt"//存储密码
设置完密码,保存密码到account.txt,退出程序,再次登录则需要密码验证。
定义一个密码判断函数
string Judge_Acc();//判断密码
bool Judge_Pass=false;//判读之前是否登录成功
定义一个密码判断次数的函数
int Acc_Num=3;//次数判断
锁定判断函数
bool Acc_Flag = false;//锁定判断
当密码进行3次错误后,将直接进行账号锁定,无法再次登录
5.1.2 词汇的添加
定义一个词汇添加函数
void Add_Words();//添加
在词汇添加的操作中同密码一样需要把添加的词汇,保存到文件中。
定义一个文件存储词汇
#define FILENAME1 "words.txt"//存储词汇
确定词汇的添加方式
添加的形式以及一次添加个数
在添加时增加一个重复判断,如果单词已存在,则输出"已经存在此词汇,请重新输入…"
当添加完之前要添加的个数后,显示添加完成保存到”words.txt”,并询问是否要继续添加
5.1.3 词汇修改
定义一个词汇修改函数
void Mod_Words();//修改
选择修改词汇的方式
如果想直接根据词汇单词或者词意修改,可以选择1,再选择具体的操作选择是根据单词还是词意修改
1、修改单词 //根据单词英文查询修改
2、修改词组 //根据汉语意思查询修改
如果检测到词库的没有的单词\词组,则输出查无此词汇,然后按任意键,
也可以选则2,直接打开词库,通过词汇的序号选择直接修改。
如果选择超出的序号则无法修改。再次重新选择序号,直至修改成功
5.1.4 词汇查找
定义一个词汇查找函数
void Que_Words();//查找
选择修改词汇的方式
如果检测到词库的没有的单词\词组,则输出查无此词汇,然后按任意键
5.1.5 词汇删除
定义一个词汇删除函数
void Del_Words();//删除
选择删除的方式
如果想直接根据词汇单词或者词意删除,可以选择1,再选择具体的操作选择是根据单词还是词意删除
如果检测到词库的没有的词汇,则输出查无此词汇,然后按任意键,输入y/n选择是否要重新删除
也可以选则2,直接打开词库,通过词汇的序号选择直接删除。
如果选择超出的序号则无法删除
5.1.6 查看词库
定义一个查看词库函数
void word::Show_Words()//显示
按照下表的格式显示词汇
5.2 学生端学习模块
5.2.1 答题
定义函数
void Start_Game();//开始学习
void Save_Game();//保存学习
void Ope_Game();//操作
void Menu_Game();//学习界
void Continue_Init();//获取等级
void random(int a[]);//随机函数
word **Grade_Words;//按等级存储词汇
void Init_Grade_Num();//数量
void Start_Game_Words(int a[]);//单词
void Start_Game_Mean(int a[]);//意思
int grade;//等级
创建一个保存等级的文件
#define FILENAME2 "grade.txt"//存储等级
设置答题升级过关的相关参数
#define object1 10//每一关的单词数量
#define object2 0.9//过关率 升级
#define object3 0.5//降级
开始答题
等级:1即第一关,第一关是随机单词,填写词意(每次只能填一个)
随机出题
答案提示
输入错误的答案
正确率大于90
50<=正确率<90
正确率小于50%
等级:2即第二关,第二关是随机词意,填写单词(每次只能填一个)
关卡设置
等级:3即第三关,第三关是随机单词或词意,填写单词或词意(每次只能填一个)
等级:4即第四关,第四关是随机词组,填写词意!(每次只能填一个)
等级:5即第五关,第五关是随机词组词意,填写词组!(每次只能填一个)
等级:6即第六关,第六关是随机词组或词意,填写词组或词意!(每次只能填一个)
5.3 附加音乐模块
音乐模块直接调用的第三方winmm库
//音乐的头文件
#include <mmsystem.h>
#pragma comment(lib,"winmm.lib")
在程序的一开始添加了背景BGM
随机出题的时候触发题目弹出的clock音效
当正确率低于90无法通关时发出call警告音效
当正确率高于90,通关升级时发出cheer胜利的欢呼音效
6 调试分析
在调试时由于查看词库的代码的逻辑出现了bug,导致出现了无法查看词库内容和异常死循环,词库一直刷新的问题。
解决方案:初始化以及错误打印输出报告,查看是否成功链入文件,并是否能对其读写
f.open(FILENAME1, ios::in | ios::out);
if (!f.is_open())
{
cout << "文件打开失败..." << endl;
return;
}
Init_Grade_Num();
if (Grade_Num == 0)
{
cout << "文件为空..." << endl;
return;
}
2.一开设计在词库删除时忘记设置词汇序号的减少导致,序号出现空缺的问题。
解决方案:删除词汇后,当前词汇后的单词全部在序号上减一
//全部移动
for (int i = j; i < Num; i++)
{
CE_Words[i] = CE_Words[i + 1];
}
//数量减一
Num--;
由于使用的codeblocks在导入第三方winmm库时出现失败,因为是是第三方库不是codeblocks内置的库,需要手动添加。
解决方案:手动添加方法。
Setting → Compiler settings → Linker settings → 在link libraries中add自己第三方库即可。
7附录
main.cpp
#include"word.h"
//声音的头文件
#include <mmsystem.h>
#pragma comment(lib,"winmm.lib")
int main()
{
system("color 6");
system("title 英语学习");
//播放
mciSendString("open bgBGM.mp3", NULL, 0, 0);
mciSendString("play bgBGM.mp3", NULL, 0, 0);
srand(time(NULL));
word CE;
while (1)
{
CE.Acc_Game();
}
return 0;
}
word.cpp
#include"word.h"
//局部颜色变化
void color(unsigned short color_index)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color_index);
}
//初始化总单词
word::word()
{
Init_Word();
}
word::~word() {
}//构造函数
void word::Init_Word()//初始化
{
fstream f;
f.open(FILENAME1, ios::in | ios::out);
if (!f.is_open())
{
cout << "文件打开失败..." << endl;
return;
}
Init_Num();
CE_Words = NULL;
if (Num == 0)
{
cout << "文件为空...." << endl;
return;
}
CE_Words = new word*[Num];//开辟大小为Num的空间
word *rd;
string w;
string m;
string a;
int k = 0;
int flag = 0;
while (getline(f, w) && getline(f, m)&&getline(f,a))
{
//分三行 一行为单词 一行为词意 一行为判断
rd = new word(w, m, a);//存入rd中
CE_Words[k] = rd;//把rd中的值存入CE_Words中
k++;
}
f.close();
}
//初始化单词数量
void word::Init_Num()//词汇的数量
{
fstream f;
f.open(FILENAME1, ios::in | ios::out);
if (!f)
{
cout << "文件打开失败..." << endl;
return;
}
string w;
string m;
string a;
int k = 0;
while (getline(f, w)&&getline(f, m)&&getline(f,a))
{
//分三行 一行为单词 一行为词意 一行为判断
// if (!(f >> a[k++]))
// break;
k++;
}
Num = k;
f.close();
}
//添加
void word::Add_Words()//添加
{
while (1)
{
cout << "1、添加单词" << endl;
cout << "2、添加词组" << endl;
cout << "0、返回" << endl;
cout << "输入你的选择:" << endl;
string type;
cin >> type;
if (type == "0")
{
return;
}
if (type == "1")
{
cout << "添加形式如单词:empleeyer " << endl;
cout << "词意:老板;雇主 (加分号为一个意思)" << endl;
}
cout << "输入你想填加的数量:" << endl;
int number;
cin >> number;
word **Add_CE_Words = new word*[Num + number];
for (int i = 0; i < Num; i++)
{
Add_CE_Words[i] = CE_Words[i];
}
word *rd;
string w;
string m;
int j;
for (int i = 0; i < number; i++)
{
bool n_flag = true;
cout << "输入你想添加的第" << i + 1 << "个词汇的单词" << endl;
if(i==0)
cin.get();
getline(cin, w);
w += ".";
if (w == ".") {
cout << "请输入单词..." << endl;
_getch();
i--;
n_flag = false;
}
if (n_flag)
{
for ( j = 0; j < Num + i; j++)
{
if (Add_CE_Words[j]->Word == w)
{
cout << "已经存在此词汇,请重新输入..." << endl;
_getch();
system("cls");
//n_flag = false;
break;
}
}
if (j != Num + i) {
i--;
}
else
{
cout << "输入你想添加的第" << i + 1 << "个词汇的词意" << endl;
// cin.get();
getline(cin, m);
m += ";";
rd = new word(w, m, type);
Add_CE_Words[Num + i] = rd;
cout << "添加成功!" << endl << endl;
}
}
}
//删掉开辟的空间
delete[]CE_Words;
//重新赋值
CE_Words = Add_CE_Words;
Num += number;
cout << "是否继续添加....(y/n)" << endl;
char ch;
cin >> ch;
if (ch == 'n')
{
Save_Words();
break;
}
}
}
//保存
void word::Save_Words()
{
fstream f;
f.open(FILENAME1, ios::in | ios::out);
if (!f.is_open())
{
cout << "文件打开失败..." << endl;
return;
}
//存入
for (int i = 0; i < Num; i++)
{
f << CE_Words[i]->Word << endl;
f << CE_Words[i]->Meaning << endl;
f << CE_Words[i]->Type << endl;
}
f.close();
}
//删除
void word::Del_Words()//删除
{
while (1)
{
string w;
string m;
string type;
int n_t;
cout << "1、输入你想删除的具体词汇的单词(注意中间空格):" << endl;
cout << "2、从词汇表中选择删除的词汇:" << endl;
cout << "0、返回" << endl;
cin >> n_t;
if (n_t == 2) {
while (1)
{
system("cls");
Show_Words();
int t;
cout << "输入你想选择删除的序号:" << endl;
cin >> t;
if (t > Num || t< 0) {
cout << "选择超出范围!" << endl;
cout << "请重新选择!" << endl;
_getch();
}
else
{
cout << "原单词:" << CE_Words[t - 1]->Word << endl;
cout << "原词意:" << CE_Words[t - 1]->Meaning << endl;
cout << "原编号:" << CE_Words[t - 1]->Type << endl;
//全部后移
for (int i = t - 1; i < Num; i++)
{
CE_Words[i] = CE_Words[i + 1];
}
//数量减一
Num--;
cout << "删除成功!" << endl;
system("pause");
cout << "是否继续删除....(y/n)" << endl;
char ch;
cin >> ch;
if (ch == 'n')
{
Save_Words();
system("cls");
break;
}
}
}
}
else if (n_t == 1)
{
cout << "1、删除单词" << endl;
cout << "2、删除词组" << endl;
cout << "输入你的选择:" << endl;
cin >> type;
cout << "输入你想要删除的单词:" << endl;
cin.get();
getline(cin, w);
w += ".";
int j = -1;
for (int i = 0; i < Num; i++)
{
if (CE_Words[i]->Word == w)
{
j = i;
}
}
if (j == -1) {
cout << "查无此词汇..." << endl;
system("pause");
cout << endl << endl;
cout << "是否重新删除...(y/n)" << endl;
char ch;
cin >> ch;
if (ch == 'n')
break;
else
system("cls");
}
else
{
//全部后移
for (int i = j; i < Num; i++)
{
CE_Words[i] = CE_Words[i + 1];
}
//数量减一
Num--;
cout << "删除成功!" << endl;
system("pause");
cout << "是否继续删除....(y/n)" << endl;
char ch;
cin >> ch;
if (ch == 'n')
{
Save_Words();
break;
}
}
}
else
if (n_t == 0) {
system("cls");
return;
}
else
{
cout << "输入有误..." << endl;
cout << "请重新输入..." << endl;
_getch();
system("cls");
}
}
}
//修改
void word::Mod_Words(