單項選擇題標準化考試系統設計
題目要求
1、問題描述 :
設計一個單項選擇題標準化考試系統,該系統要求能自動組卷和評分。
2、功能要求
(1)用文件保存試題庫。(每個試題包括題幹、4 個備選答案、標準答案)。
(2)試題錄入:可隨時增加試題到試題庫中。
(3)試題抽取:每次從試題庫中可以隨機抽出 N 道題(N 由鍵盤輸入)。
(4)答題:用戶可實現輸入自己的答案。
(5)自動判卷:系統可根據用戶答案與標準答案的對比實現判卷並給出成績。
(6)退出。
思路分析
考試系統,得有題目,先做一個題目類,就定義這些變量吧
然後對這個題進行分析歸納,通過功能要求初步確定要有這些模塊~
有登錄模塊當然也應該有包含用戶名和密碼的用戶類啦
簡簡單單~
接下來分別實現各個模塊
各個模塊的實現
題目類的創建
創建Timu.h頭文件,然後隨便寫上變量就完事了~上代碼:
class Timu {
public:
Timu() {}
~Timu() {}
string tigan;
string A, B, C, D;
char answer;
void show() {
cout << tigan << endl;
cout << "A." << A << endl;
cout << "B." << B << endl;
cout << "C." << C << endl;
cout << "D." << D << endl;
}
};
管理題庫模塊的實現
整個題庫用一個 Timu 類型的 vector 實現。
管理題庫這事哪能是什麼人都能幹的?當然要設置權限了
bool quanxian()
{
cout << "請輸入密碼來證明您的權限" << endl;
string c;
cin >> c;
return c == "73748156";
}
7 3 7 4 8 1 5 6
今生今世伴你左右 ~ 挺好挺好
出題功能的實現
因爲是用 vector 實現的題庫,所以直接輸入相關信息後插入 vector 就行,簡簡單單,看代碼:
void addTimu(vector<Timu>& a) {
Timu temp;
string s, A, B, C, D, ans;
cout << "請輸入題幹" << endl;
cin >> temp.tigan;
cout << "請輸入A選項" << endl;
cin >> temp.A;
cout << "請輸入B選項" << endl;
cin >> temp.B;
cout << "請輸入C選項" << endl;
cin >> temp.C;
cout << "請輸入D選項" << endl;
cin >> temp.D;
cout << "請輸入正確選項" << endl;
cin >> temp.answer;
if (temp.answer >= 'a' && temp.answer <= 'z')temp.answer = temp.answer - 32;
a.push_back(temp);
cout << "添加完成" << endl;
}
突然覺得這個三級項目寫的沒有激情。。。。有點簡單。。
題目的存儲與讀取
大概不能每次考試都重新打一遍題。。。太不人性化了
就把題庫存到本地文件裏吧
這裏要用到c++文件流來實現,上代碼
存儲:
void save(vector<Timu>& a)
{
ofstream ofs;
ofs.open(FILENAME, ios::out);
for (auto& i : a) {//錄入每道題信息
ofs << i.tigan << "\n" << i.A << "\n" << i.B << "\n"
<< i.C << "\n" << i.D << "\n" << i.answer << endl;
//將所有信息存儲
}
cout << "保存成功" << endl;
ofs.close();//關閉文件
}
讀取也差不多
void fetch(vector<Timu>& a)
{
ifstream ifs;
ifs.open(FILENAME, ios::in);//讀文件
if (!ifs.is_open())//判斷是否存在
{
cout << "題庫文件不存在" << endl;
ifs.close();
return;
}
Timu i;
while (ifs >> i.tigan >> i.A >> i.B >> i.C >> i.D >> i.answer)//信息讀取到temp中
{
a.push_back(i);
}
ifs.close();
if (a.empty())
{
cout << "題庫爲空" << endl;
}
else
cout << "當前題目數目爲" << a.size() << "道" << endl;
}
把讀取加在主函數裏,保存放到出題同級菜單下就好
封裝題庫管理模塊
加一個滿足理科生審美的菜單
void showMenu2()
{
cout << "*********************************" << endl;
cout << "******* 學習使我快樂 ******" << endl;
cout << "******* 出題請按 1 ******" << endl;
cout << "******* 保存題庫請按 2 ******" << endl;
cout << "******* 退出請按 0 ******" << endl;
cout << "*********************************" << endl;
}
我愛學習,學習使我快樂!
用switch實現整理題庫的封裝函數
void arrangeTiku(vector<Timu>& a) {
char c;
while (true)
{
showMenu2();
cin >> c;
switch (c) {
case '0'://退出
return;
case '1'://出題
addTimu(a);
break;
case '2'://保存
save(a);
break;
}
system("pause");
system("cls");
}
}
完美 ~ ~ 此處應該有掌聲鼓勵!
考試模塊的實現
抽題功能的實現
c++沒有封裝隨機數的方法,查了好多才知道該怎麼在一定範圍內取隨機數,先加個這個#define random(x) (rand()%x)
然後在函數中這樣調用就可以在指定範圍內出隨機數啦 ~
肯定要讀入 N(抽取題目數量),把 N 傳進函數裏
void chouTimu(vector<Timu>a, vector<Timu>& b, int N)
{
int x;
for (int i = 0; i < N; ++i) {
x = random(a.size());
b.push_back(a[x]);
a.erase(a.begin() + x);
}
}
將抽出來的題目存在一個新的 Timu 類型 vector 中就完事啦 ~ 輕輕鬆鬆 ~ ~ ~
答題功能的實現
傳入剛纔抽出來的題目,讀入答案,判斷並記數,最後返回成績
int answerTi(vector<Timu>a) {
char c;
int x = 0;
for (int i = 0; i < a.size(); ++i) {
a[i].show();
cout << "請輸入你的答案" << endl;
cin >> c;
if (c >= 'a' && c <= 'z')c = c - 32;
if (c == a[i].answer)x++;
}
return 100 * x / a.size();
}
嘖 ~ 這三級項目就快要完事了
考試模塊的封裝
讀入要答題的數目,注意判斷下題庫裏題目夠不夠就行
簡簡單單,直接上代碼
void takeExam(vector<Timu>& a) {
cout << "請輸入你想要答題的數目" << endl;
int N;
cin >> N;
if (N > a.size())
{
cout << "當前題目數量不足" << endl;
return;
}
vector<Timu>b;
chouTimu(a, b, N);
int score = answerTi(b);
cout << "你的成績是" << score << endl;
}
完事,下一個 ~
用戶類的創建
沒啥可說的,就這倆變量
class User {
public:
string password;
string userName;
};
太簡單,感覺他不配二級目錄。。。。。
登錄模塊的創建
無非就是註冊和登錄,記得註冊的時候把他用文件流存到本地文件裏,下次還能登錄就好 ~
先聲明一個判斷用戶名是否存在的函數
代碼如下:
int isUserExist(string name, vector<User>u) {
for (int i = 0; i < u.size(); ++i) {
if (u[i].userName == name) return i;
}
return -1;
}
接着是註冊的代碼:
void zhuce(vector<User>& u)
{
string password;
User tmp;
string name;
cout << "請輸入用戶名" << endl;
cin >> name;
int a = isUserExist(name, u);
if (a == -1)
{
tmp.userName = name;
cout << "請輸入密碼" << endl;
cin >> password;
tmp.password = password;
u.push_back(tmp);
ofstream ofs;
ofs.open(FILENAME2, ios::out);
for (auto& i : u) {//錄入用戶信息
ofs << i.userName << " " << i.password << endl;
}
cout << "保存成功" << endl;
ofs.close();//關閉文件
}
else cout << "該用戶名已被使用,註冊失敗" << endl;
}
要記得判斷用戶名是否重複,以免出現問題 ~
然後是登錄的代碼:
bool denglu(vector<User>& u) {
string name, password;
cout << "請輸入用戶名" << endl;
cin >> name;
int a = isUserExist(name, u);
if (a == -1) {
cout << "用戶名不存在,登錄失敗" << endl;
return false;
}
else
{
cout << "請輸入密碼" << endl;
cin >> password;
if (u[a].password == password) {
cout << "登錄成功" << endl;
return true;
}
else
{
cout << "密碼錯誤,登錄失敗" << endl;
return false;
}
}
}
遍歷判斷密碼對不對就行
然後做一個美麗的菜單
void showMenu3() {
cout << "*********************************" << endl;
cout << "******* 學習使我快樂 ******" << endl;
cout << "******* 登錄請按 1 ******" << endl;
cout << "******* 註冊請按 2 ******" << endl;
cout << "******* 退出請按 0 ******" << endl;
cout << "*********************************" << endl;
}
注意這裏要停一會,好好欣賞下菜單再往下 ~ ~ ~ ~
最後封裝到一起就好啦
主函數的封裝
創建兩個 vector ,然後讀入本地文件到 vector 中,接後邊的主菜單函數,通過主菜單函數封裝所有模塊 ~
int main() {
vector<Timu>tiku;
vector<User>yonghu;
fetch(tiku);
fetchUser(yonghu);
select(tiku, yonghu);
return 0;
}
主菜單選項的封裝
要先做一個主菜單
void showMenu1()
{
cout << "******************************" << endl;
cout << "******* 學習使我快樂 ******" << endl;
cout << "******* 考試請按 1 ******" << endl;
cout << "******* 整理題庫請按 2 ******" << endl;
cout << "******* 退出請按 0 ******" << endl;
cout << "******************************" << endl;
}
樣式還是依舊絕色
void select(vector<Timu>& a, vector<User>& b) {
char s,choose0;
int h = 0;
do {
showMenu3();
cin >> choose0;
switch (choose0)
{
case'1'://登錄
if (denglu(b))
{
h = 1;
break;
}
else
continue;
case'2'://註冊
zhuce(b);
break;
case'0':
cout << "歡迎下次使用" << endl;
return;
}
system("pause");
system("cls");
} while ((choose0 != '0' && h != 1));
while (true)
{
showMenu1();
cin >> s;
switch (s) {
case '0'://退出
cout << "歡迎下次使用" << endl;
return;
case '1'://考試
takeExam(a);
break;
case '2'://整理題庫
if (quanxian())
arrangeTiku(a);
else cout << "密碼錯誤,您沒有權限" << endl;
break;
default:
cout << "指令錯誤,請重新輸入" << endl;
break;
}
system("pause");
system("cls");
}
}
三級項目完成 ~ 是不是還挺簡單的 ?
成品也上傳到這裏啦
燕大的朋友們也可以私信找我要代碼的