• 驾照考试系统


    其实本程序主要是熟悉了windows系统的应用程序基于消息机制的编程,同时熟悉了几个控件的操作,下面上主要的代码

    新建一个基于DLG的mfc程序,加上下面的头文件

    #include <iostream>
    using namespace std;
    //问题的结构体
    struct Question
    {
        string question;
        string answer[4];
        int right_answer;
    };
    //定义全局变量  100个题目
    Question quest[100];
    question.h头文件

    DLG成员

    class CTESTDlg : public CDialog
    {
    // Construction
    public:
        CTESTDlg(CWnd* pParent = NULL);    // standard constructor
    
    // Dialog Data
        //{{AFX_DATA(CTESTDlg)
        enum { IDD = IDD_TEST_DIALOG };
            // NOTE: the ClassWizard will add data members here
        //}}AFX_DATA
    
        // ClassWizard generated virtual function overrides
        //{{AFX_VIRTUAL(CTESTDlg)
        protected:
        virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
        //}}AFX_VIRTUAL
    
    // Implementation
    protected:
        HICON m_hIcon;
    
        // Generated message map functions
        //{{AFX_MSG(CTESTDlg)
        virtual BOOL OnInitDialog();
        afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
        afx_msg void OnPaint();
        afx_msg HCURSOR OnQueryDragIcon();
        afx_msg void OnStudy();
        afx_msg void OnSelchangeAnswers();
        afx_msg void OnTest();
        afx_msg void OnNextbt();
        //}}AFX_MSG
        DECLARE_MESSAGE_MAP()
    private:
        int mark;//考试分值,五个题目,一个20分,满分100
        int QS[5];//随机题库序号
        int count2;//题库总数
        int count_Q;//当前输出的题目数量
    };
    DLG的成员

     其中count2用来保存读取的题目的个数,count_Q用来保存当前输出的题目个数,mark为考试当前得分,QS保存每次进入考试的时候随机生成的考试题目序号

    DLG的初始化代码

    BOOL CTESTDlg::OnInitDialog()
    {
        CDialog::OnInitDialog();
    
        // Add "About..." menu item to system menu.
    
        // IDM_ABOUTBOX must be in the system command range.
        ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
        ASSERT(IDM_ABOUTBOX < 0xF000);
    
        CMenu* pSysMenu = GetSystemMenu(FALSE);
        if (pSysMenu != NULL)
        {
            CString strAboutMenu;
            strAboutMenu.LoadString(IDS_ABOUTBOX);
            if (!strAboutMenu.IsEmpty())
            {
                pSysMenu->AppendMenu(MF_SEPARATOR);
                pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
            }
        }
    
        // Set the icon for this dialog.  The framework does this automatically
        //  when the application's main window is not a dialog
        SetIcon(m_hIcon, TRUE);            // Set big icon
        SetIcon(m_hIcon, FALSE);        // Set small icon
    
        // TODO: Add extra initialization here
        //读取题目,放置到题目结构体中
        CFile file("test.txt",CFile::shareExclusive);
        char *pBuf;
        DWORD len;
        len = file.GetLength();
        pBuf = new char[len+1];
        pBuf[len] = '';
        file.Read(pBuf,len);
        file.Close();
        //将缓冲区的题目转换至结构体中 count用于计算复制给那个结构体中的东西
        int count = 0;
        count2 = 0;
        for (int i = 0,j = 0;pBuf[j] != '';j++)
        {
            if (pBuf[j] == '
    ')
            {
                char * temp = new char[j-i+1];
                temp[j-i] = '';
                for (int k = i;k < j;k++)
                {
                    temp[k-i] = pBuf[k];
                }
                
                if (count%6 == 0)
                {
                    quest[count2].question.append(temp,j-i);
                }
                if (count%6 == 1)
                {
                    quest[count2].answer[0].append(temp,j-i);
                }
                if (count %6 == 2)
                {
                    quest[count2].answer[1].append(temp,j-i);
                }
                if (count %6 == 3)
                {
                    quest[count2].answer[2].append(temp,j-i);
                }
                if (count %6 == 4)
                {
                    quest[count2].answer[3].append(temp,j-i);
                }
                if (count %6 == 5)
                {
                    quest[count2].right_answer = atoi(temp);
                    count2++;
                }
                delete temp;
                i = j;
                count++;
            }
        }
    
        return TRUE;  // return TRUE  unless you set the focus to a control
    }
    DLG对话框初始化代码

    这里主要是用了一个读取文件的算法,首先将放置在记事本中以相同格式摆放的字符读取到缓冲区中,然后按照循环将字符串分离,放置到指定的结构体中,这里就完成了题库的初始化,其中算法流程如下:

    下面就是主界面框的响应函数了,在主界面添加了下面的几个控件,左下角的listbox空间,右边的下一题按钮,还有listbox上面的一个编辑框(),,其中,编辑框用来防止题目,listbox用来防止选项(假如是学习模式,那么listbox显示正确答案).然后是正确和取消按钮都是退出程序(新建向导自动生成的,也懒得删除了.)

     下面咱们开始做东西了哈.首先是添加单选按钮的相应函数如下

    void CTESTDlg::OnStudy() 
    {
        // TODO: Add your control notification handler code here
        //将题目计数器置0,同时将listbox控件清空,插入第一个题目,放置正确答案在控件中
        count_Q = 0;
        ((CListBox*)GetDlgItem(IDC_ANSWERS))->ResetContent();
        SetDlgItemText(IDC_EDITQT,quest[count_Q].question.c_str());
        ((CListBox*)GetDlgItem(IDC_ANSWERS))->AddString((quest[count_Q].answer[quest[count_Q].right_answer].c_str()));
    }
    学习按钮响应函数
    void CTESTDlg::OnTest() 
    {
        // TODO: Add your control notification handler code here
        //初始化获得分值
        mark = 0;
        //初始化随机数种子
        srand((int)time(0));
        //生成将要考试的10个随机数题目
        int *NBuf = new int[count2];
        for(int i = 0;i <= count2;i++)
            NBuf[i] = i;
    
        for (i = 0;i <= 4;i++)
        {
            int temp = rand()%(count2+1);
            while(NBuf[temp] == -1)
            {
                temp = rand()%(count2+1);
            }
            QS[i] = NBuf[temp];
            NBuf[temp] = -1;
        }
    
        //将题目计数器置0,同时将listbox控件清空,插入第一个题目,放置所有答案在控件中
        count_Q = 0;
        ((CListBox*)GetDlgItem(IDC_ANSWERS))->ResetContent();
        SetDlgItemText(IDC_EDITQT,quest[count_Q].question.c_str());
        for(i = 0;i <= 3;i++)
        ((CListBox*)GetDlgItem(IDC_ANSWERS))->AddString((quest[QS[count_Q]].answer[i].c_str()));
    }
    考试按钮响应函数

    下面咱们仔细分析下,

    当我们按下学习按钮,首先将当前输出题目count_Q置为0,即第一个题目,然后将对应的题目和正确答案放置于相应的控件上.

    假如按下的是考试按钮,首先同样将count_Q置0,但是这里的准备工作要稍微多点,因为涉及到随机生成的问题,成绩初始化为0,初始化随机数种子,然后生成一个随机数数列,且里面的数不重复(生成算法专门罗列),然后将保存的随即题目的第一题输出.

    下面是最重要的下一题按钮的响应函数.代码如下:

    void CTESTDlg::OnNextbt() 
    {
        if (GetCheckedRadioButton(IDC_STUDY,IDC_TEST) == IDC_STUDY)
        {//如果是选择的学习
            count_Q++;
            if (count_Q == count2+1)
            {
                MessageBox("题库已完","提示",MB_OK);
            }
            ((CListBox*)GetDlgItem(IDC_ANSWERS))->ResetContent();
            SetDlgItemText(IDC_EDITQT,quest[count_Q].question.c_str());
            ((CListBox*)GetDlgItem(IDC_ANSWERS))->AddString((quest[count_Q].answer[quest[count_Q].right_answer].c_str()));
        }
        else if(GetCheckedRadioButton(IDC_STUDY,IDC_TEST) == IDC_TEST)
        {//选择的是考试
            count_Q++;
            //进行成绩判定
            if ((((CListBox*)GetDlgItem(IDC_ANSWERS))->GetCurSel()) ==quest[count_Q-1].right_answer)
            {
                mark++;
            }
            if (5 ==count_Q)
            {
                string temp = "考试已经考完,您的成绩为:";
                char t[5];
                itoa(mark*20,t,10);
                temp.append(t);
                MessageBox(temp.c_str());
                return;
            }
            //清空listbox和编辑框,然后输入下个题目
            ((CListBox*)GetDlgItem(IDC_ANSWERS))->ResetContent();
           SetDlgItemText(IDC_EDITQT,quest[QS[count_Q]].question.c_str());
           for(int j = 0;j <= 3;j++)
            ((CListBox*)GetDlgItem(IDC_ANSWERS))->AddString((quest[QS[count_Q]].answer[j].c_str()));
        }else
        {//防止未选择类型而导致程序崩溃
            MessageBox("请选择 学习 或者 考试类型");
            return;
        }
    }
    NextButton响应函数

    首先判断当前选定的是学习还是考试按钮,假如是学习,将题目计数器++,然后判定题库是否用完,然后清空控件,输出下一个题目及答案.

    假如选定的考试,首先判定是否在listbox里面选定了某个答案,若没有,则跳出函数,return,否则将题目计数器++,然后判定选定的答案是否是正确答案,正确,则mark++,下面判断要考试的5个题目是否已经考完,假如考完了,则提示当前得分,若没考完,则输出下一个随机题目.

    如果没有选定单选按钮,则提示要选择,不然程序会崩溃.

    上面就是整个流程,在编程过程中,遇到很多的困难,尤其是控件的使用问题,全部是自己百度+摸索得出来的.然后就是这次自己写了一个读取文件的算法,学习了一个用空间换取时间的不同的随机数生成算法,感觉还是蛮好

    本次编程中感觉自己略显不足的地方:

    1.编程的时候思绪不够清晰,比较混乱,尤其是变量的命名,多了以后就分不清了.下次注意

    不过欣慰的是,虽然写程序遇到过很多问题,但是都凭着良好的感觉将问题给解决了.

    替换了默认的图标,感觉不错,附上最喜欢的钢琴曲一首

  • 相关阅读:
    thoughtworks家庭作业C++版本
    删除数组中等于某个key的所有元素
    一些必读的开源项目
    库函数strlen源码重现及注意问题
    判断相同树或者对称树
    约瑟夫环问题
    Loadrunner 脚本录制策略
    品味性能之道<十一>:JAVA中switch和if性能比较
    白盒静态自动化测试工具:FindBugs使用指南
    六个步骤把资料转换成知识
  • 原文地址:https://www.cnblogs.com/color-my-life/p/3213524.html
Copyright © 2020-2023  润新知