Android实训案例(九)——答题系统的思绪,自己设计一个题库的体验,一个思路清晰的答题软件制作过程

Android实训案例(九)——答题系统的思绪,自己设计一个题库的体验,一个思路清晰的答题软件制作过程


项目也是偷师的,决心研究一下数据库。所以写的还是很详细的,各位看官,耐着性子看完,实现结果不重要,思路一定要清晰,我们做一个简单的项目,所以也就设计的比较简陋了,首先新建一个项目——AnswerSystem

一.实现项目框架

主页面就是一个问题,四个答案,还有一个正确答案,最后就是翻页了,正确答案默认是隐藏的,所以我们的layout_mian.xml是这样实现的

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:padding="20dp">

            <TextView
                android:id="@+id/tv_title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="问:刘桂林是何许人也?"
                android:textColor="@color/colorAccent"
                android:textSize="22sp"
                android:textStyle="bold" />

            <RadioGroup
                android:id="@+id/mRadioGroup"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp">

                <!--四个选项-->

                <RadioButton
                    android:id="@+id/RadioA"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="大帅哥" />

                <RadioButton
                    android:id="@+id/RadioB"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="参照A" />

                <RadioButton
                    android:id="@+id/RadioC"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="参照B" />

                <RadioButton
                    android:id="@+id/RadioD"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="参照C" />

                <!--正确答案,默认是隐藏的-->

                <TextView
                    android:visibility="invisible"
                    android:id="@+id/tv_result"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="10dp"
                    android:text="正确答案:肯定选A呀!"
                    android:textColor="@color/colorPrimaryDark"
                    android:textSize="18sp" />

            </RadioGroup>

        </LinearLayout>

    </ScrollView>

    <!--切换题目-->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:orientation="horizontal">

        <Button
            android:id="@+id/btn_up"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="上一题" />

        <Button
            android:id="@+id/btn_down"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="下一题" />

    </LinearLayout>

</LinearLayout>

我们来预览一下

二.数据库的设计

数据库的话,我们采用一个轻量级数据库编辑器去编辑Sqlite Database Browser

当然,你也可直接搜索这个软件也是可以下载到的,然后点击安装,一步步安装就可以完成了

我们在这里就点击新建数据库——question.db,然后就添加了一些参数,主要就是编号和问题,四个选项,答案,解析等

然后我们点击浏览数据,这里我们可以看到我这里设置的表明对应的说明

既然这样,那我们就多写几个问题吧

紧接着,我们要考虑的一个问题就是,把这个数据库放到软件的数据库里面,所以我先把question.db放在assets目录下,然后通过以下的方法区拷贝到app目录

/**
     * 将数据库拷贝到相应目录
     */
    private void initFile() {
        //判断数据库是否拷贝到相应的目录下
        if (new File(DB_PATH + DB_NAME).exists() == false) {
            File dir = new File(DB_PATH);
            if (!dir.exists()) {
                dir.mkdir();
            }

            //复制文件
            try {
                InputStream is = getBaseContext().getAssets().open(DB_NAME);
                OutputStream os = new FileOutputStream(DB_PATH + DB_NAME);

                //用来复制文件
                byte[] buffer = new byte[1024];
                //保存已经复制的长度
                int length;

                //开始复制
                while ((length = is.read(buffer)) > 0) {
                    os.write(buffer, 0, length);
                }

                //刷新
                os.flush();
                //关闭
                os.close();
                is.close();

            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

三.答题功能实现

当这个方法执行了之后,你运行了软件,你在data/data/包名/database目录下就可以看到这个数据库了,这样我们就可以先去定义一个类专门用来存储数据——Question

package com.lgl.answersystem;

/**
 * 保存数据库数据
 * Created by LGL on 2016/6/4.
 */
public class Question {

    /**
     * 对应的就是Filter1-7  还有一个选中答案
     */

    //编号
    public int ID;
    //问题
    public String question;
    //四个选项
    public String answerA;
    public String answerB;
    public String answerC;
    public String answerD;
    //答案
    public int answer;
    //详情
    public String explaination;

    //用户选中的答案
    public int selectedAnswer;

}

紧接着,我们写一个数据库的类,专门连接数据库和获取数据——DBService

package com.lgl.answersystem;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import java.util.ArrayList;
import java.util.List;

/**
 * 连接数据库
 * Created by LGL on 2016/6/4.
 */
public class DBService {

    private SQLiteDatabase db;

    //构造方法
    public DBService() {
        //连接数据库
        db = SQLiteDatabase.openDatabase("/data/data/com.lgl.answersystem/databases/question.db", null, SQLiteDatabase.OPEN_READWRITE);

    }

    //获取数据库的数据
    public List<Question> getQuestion() {
        List<Question> list = new ArrayList<>();
        //执行sql语句
        Cursor cursor = db.rawQuery("select * from question", null);
        if (cursor.getCount() > 0) {
            cursor.moveToFirst();
            int count = cursor.getCount();
            //遍历
            for (int i = 0; i < count; i++) {
                cursor.moveToPosition(i);
                Question question = new Question();
                //ID
                question.ID = cursor.getInt(cursor.getColumnIndex("Field1"));
                //问题
                question.question = cursor.getString(cursor.getColumnIndex("Field2"));
                //四个选择
                question.answerA = cursor.getString(cursor.getColumnIndex("Field3"));
                question.answerB = cursor.getString(cursor.getColumnIndex("Field4"));
                question.answerC = cursor.getString(cursor.getColumnIndex("Field5"));
                question.answerD = cursor.getString(cursor.getColumnIndex("Field6"));
                //答案
                question.answer = cursor.getInt(cursor.getColumnIndex("Field7"));
                //解析
                question.explaination = cursor.getString(cursor.getColumnIndex("Field8"));
                //设置为没有选择任何选项
                question.selectedAnswer = -1;
                list.add(question);
            }
        }
        return list;

    }

}

OK,到这里,我们的数据库算是写好了一大半了,我们这里可以看到,其实就是查询我们的数据库然后封装在这个实体类中,紧接着,我们可以先初始化一些控件

    /**
     * 初始化View
     */
    private void initView() {
        tv_title = (TextView) findViewById(R.id.tv_title);

        mRadioButton[0] = (RadioButton) findViewById(R.id.RadioA);
        mRadioButton[1] = (RadioButton) findViewById(R.id.RadioB);
        mRadioButton[2] = (RadioButton) findViewById(R.id.RadioC);
        mRadioButton[3] = (RadioButton) findViewById(R.id.RadioD);

        btn_down = (Button) findViewById(R.id.btn_down);
        btn_up = (Button) findViewById(R.id.btn_up);

        tv_result = (TextView) findViewById(R.id.tv_result);

        mRadioGroup = (RadioGroup) findViewById(R.id.mRadioGroup);
    }

接着就开始实现我们的答题系统了

    /**
     * 初始化数据库服务
     */
    private void initDB() {
        DBService dbService = new DBService();
        final List<Question> list = dbService.getQuestion();

        count = list.size();
        corrent = 0;

        Question q = list.get(0);
        tv_title.setText(q.question);

        mRadioButton[0].setText(q.answerA);
        mRadioButton[1].setText(q.answerB);
        mRadioButton[2].setText(q.answerC);
        mRadioButton[3].setText(q.answerD);

        //上一题
        btn_up.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (corrent > 0) {
                    corrent--;

                    Question q = list.get(corrent);

                    tv_title.setText(q.question);

                    mRadioButton[0].setText(q.answerA);
                    mRadioButton[1].setText(q.answerB);
                    mRadioButton[2].setText(q.answerC);
                    mRadioButton[3].setText(q.answerD);

                    tv_result.setText(q.explaination);

                    mRadioGroup.clearCheck();

                    //设置选中
                    if (q.selectedAnswer != -1) {
                        mRadioButton[q.selectedAnswer].setChecked(true);
                    }
                }

            }
        });

        //下一题
        btn_down.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //判断是否为最后一题
                if (corrent < count - 1) {
                    corrent++;
                    Question q = list.get(corrent);

                    tv_title.setText(q.question);

                    mRadioButton[0].setText(q.answerA);
                    mRadioButton[1].setText(q.answerB);
                    mRadioButton[2].setText(q.answerC);
                    mRadioButton[3].setText(q.answerD);

                    tv_result.setText(q.explaination);

                    mRadioGroup.clearCheck();

                    //设置选中
                    if (q.selectedAnswer != -1) {
                        mRadioButton[q.selectedAnswer].setChecked(true);
                    }
                } else {
                    Toast.makeText(MainActivity.this, "最后一题啦!", Toast.LENGTH_SHORT).show();
                }
            }
        });

        //答案选中
        mRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                for (int i = 0; i <4 ; i ++){
                    if(mRadioButton[i].isChecked() == true){
                        list.get(corrent).selectedAnswer = i;
                        break;
                    }
                }
            }
        });
    }

现在的逻辑还是非常的简单的,我们连接数据库拿到数据,点击上一题和下一题的时候,就开始切换数据,我们并没有对他进行什么很难的处理,我们运行一下

四.答错解析

我们在上面实现了答题的功能,同时,也实现了保存选项的功能,拿这样的话,我们就可以再来实现一个判断错误的方法

     /**
     * 判断是否答题正确
     * @param list
     * @return
     */
    private List<Integer> checkAnswer(List<Question>list){
        List<Integer>wrongList= new ArrayList<>();
        for(int i = 0 ; i<list.size();i++){
            //判断对错
            for (list.get(i).answer != list.get(i).selectedAnswer){
                wrongList.add(i);
            }
        }
        return wrongList;
    }

然后我们就可以在点击按钮到最后一题的时候判断是否正确了

//没有题目了,开始检测正确性
                    final List<Integer> wrongList = checkAnswer(list);

                    if(wrongList.size() == 0){
                        new AlertDialog.Builder(MainActivity.this).setTitle("提示").setMessage("你好厉害,答对了所有题!")
                                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        finish();
                                    }
                                }).setNegativeButton("取消",null).show();
                    }

                    //窗口提示
                    new AlertDialog.Builder(MainActivity.this).setTitle("恭喜,答题完成!")
                            .setMessage("答对了" + (list.size() - wrongList.size()) + "道题" + "\n"
                                    + "答错了" + wrongList.size() + "道题" + "\n" + "是否查看错题?").setPositiveButton("确定", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            wrongMode = true;
                            List<Question> newList = new ArrayList<Question>();
                            for (int i = 0; i < wrongList.size(); i++) {
                                newList.add(list.get(wrongList.get(i)));
                            }
                            list.clear();
                            for (int i = 0; i < newList.size(); i++) {
                                list.add(newList.get(i));
                            }
                            corrent = 0;
                            count = list.size();

                            //更新当前显示的内容
                            Question q = list.get(corrent);

                            tv_title.setText(q.question);

                            mRadioButton[0].setText(q.answerA);
                            mRadioButton[1].setText(q.answerB);
                            mRadioButton[2].setText(q.answerC);
                            mRadioButton[3].setText(q.answerD);

                            tv_result.setText(q.explaination);
                            //显示结果
                            tv_result.setVisibility(View.VISIBLE);
                        }
                    }).setNegativeButton("取消", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            finish();
                        }
                    }).show();

这里,开始是一个判断你全答对的情况下,那就直接提示你正确,否则的话,也就开始进行处理了,同时,你要查看错题的话,你就的切换错题模式,我们就重新加载数据了,这里还会有几个情况,比如当我们查看错题有点击到最后一题的时候,我们可以直接弹提示

        else if (corrent == count - 1 && wrongMode == true) {

                    new AlertDialog.Builder(MainActivity.this).setTitle("提示").setMessage("已经到达最后一道题,是否退出?")
                            .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    finish();
                                }
                            }).setNegativeButton("取消",null).show();

这样,我们简单的答题系统就差不多完成了,我们来运行一下

这个实现起来还是比较清晰脱俗的,我们可以点击在数据库里面任意的添加题目,这都是OK的,项目我上传到了Github上,有兴趣的可以看一下哦!

Github:https://github.com/LiuGuiLinAndroid/AnswerSystem

欢迎加群:555974449一起讨论技术兴趣!

时间: 2024-09-17 04:20:36

Android实训案例(九)——答题系统的思绪,自己设计一个题库的体验,一个思路清晰的答题软件制作过程的相关文章

Android实训案例(五)——四大组件之一ContentProvider的使用,通讯录的实现以及ListView的优化

Android实训案例(五)--四大组件之一ContentProvider的使用,通讯录的实现 Android四大组件是啥这里就不用多说了,看图吧,他们之间通过intent通讯 我们后续也会一一的为大家讲解,今天就使用内容提供者ContentProvider查询系统的数据库来获取联系人,我们用listview装载 我们新建一个项目就叫MyPhone吧 并且添加权限 <uses-permission android:name="android.permission.READ_CONTACTS

Android实训案例(六)——四大组件之一BroadcastReceiver的基本使用,拨号,短信,SD卡,开机,应用安装卸载监听

Android实训案例(六)--四大组件之一BroadcastReceiver的基本使用,拨号,短信,SD卡,开机,应用安装卸载监听 Android中四大组件的使用时重中之重,我这个阶段也不奢望能把他所有的原理搞懂,但是最起码的,我要把他的各种使用方法了如指掌才行 BroadcastReceiver 接收系统的广播,比如电话,短信之类的 1.IP拨号器 我们在拨打电话的时候,我们系统也会事先发送一个广播,所以我们可以用广播接收者来接收到这个广播拨打电话的时候在电话号码前面加上一些优惠的长途短号,

Android实训案例(四)——关于Game,2048方块的设计,逻辑,实现,编写,加上色彩,分数等深度剖析开发过程!

Android实训案例(四)--关于Game,2048方块的设计,逻辑,实现,编写,加上色彩,分数等深度剖析开发过程! 关于2048,我看到很多大神,比如医生,郭神,所以我也研究了一段时间,还好是研究了一套逻辑,这是一整套的2048游戏从设计到逻辑再到编写的全部过程,小伙伴们看仔细咯,刚好今天是礼拜天,一天应该了一把这篇博客发表了,其实2048开发起来还是有点难度的,并且他的逻辑挺强的,我也是看了很多的资料偷学的,很适合来锻炼自己的逻辑性 我们首先先来选择开发环境,这里我们就以Eclipse为I

Android实训案例(八)——单机五子棋游戏,自定义棋盘,线条,棋子,游戏逻辑,游戏状态存储,再来一局

Android实训案例(八)--单机五子棋游戏,自定义棋盘,线条,棋子,游戏逻辑,游戏状态存储,再来一局 阿法狗让围棋突然就被热议了,鸿洋大神也顺势出了篇五子棋单机游戏的视频,我看到了就像膜拜膜拜,就学习了一下,写篇博客梳理一下自己的思路,加深一下印象 视频链接:http://www.imooc.com/learn/641 一.棋盘 我们一看就知道,我们必须自定义View,这里我们定义一个GameView来做游戏主类,第一步,先测量,我们这里不难知道,五子棋他的棋盘是一个正方形,所以我们需要去测

Android实训案例(三)——实现时间轴效果的ListView,加入本地存储,实现恋爱日记的效果!

Android实训案例(三)--实现时间轴效果的ListView,加入本地存储,实现恋爱日记的效果! 感叹离春节将至,也同时感叹时间不等人,一年又一年,可是我依然是android道路上的小菜鸟,这篇讲的是时间轴的实现,说实话,其实就是listview的偷梁换柱,本来我会在写listview这个系列的时候写的,但是最近自己写的一个项目<Only>上用到了,很多群友说也想看看怎么实现的,独乐乐不如众乐乐,所以就提前先来分享,说说listview,这可是一个名角,在android上很受欢迎,也很实用

Android实训案例(一)——计算器的运算逻辑

Android实训案例(一)--计算器的运算逻辑 应一个朋友的邀请,叫我写一个计算器,开始觉得,就一个计算器嘛,很简单的,但是写着写着发现自己写出来的逻辑真不严谨,于是搜索了一下,看到mk(没有打广告-.)上有视频,于是看了下他的逻辑,以前还真是小瞧计算器了,计算器要是高级一点的处理起来更加繁琐,这里就做了一个简单一点的,这次用的是Android Studio 开发的,毕竟自己也是一直很推崇AS,但是在之前的博客里都只是为了方便,一直在用Eclipse 一直强烈推荐大家还是转移到AS上去,虽然我

Android实训案例(七)——四大组件之一Service初步了解,实现通话录音功能,抽调接口

Service Service的神奇之处,在于他不需要界面,一切的操作都在后台操作,所以很多全局性(手机助手,语音助手)之类的应用很长需要这个,我们今天也来玩玩 我们新建一个工程--ServiceDemo 1.启动服务 服务是怎么启动的,我们先定义一个按钮吧 <Button android:id="@+id/startservice" android:layout_width="wrap_content" android:layout_height="

系统操作日志的设计,大家有什么好的思路?

问题描述 我现在要做一个人事管理系统,客户提出资料在修改时需要申请审核,在审核时需要把修改的字段以及修改之前和修改之后的值都列出来.不知道大家有什么好的思路?? 解决方案 针对需要的业务模块,添加一个影像表.该报和业务表结构基本相同(注意关联关系).审批页面,分别从业务表和业务相应的影像表取数据,给予展示.用户一直操作的是影像表,待审批通过后,用影响表覆盖业务表,同时删除影像表数据.这里的删除得考虑一下,是物理删除还是逻辑删除.若数据重要,建议逻辑删除(注意数据的备份).创建个表,记录每一条SQ

H3C为北京一轻高级技工学校打造精品网络实训室

网络实训室需求高涨 北京一轻高级技工学校是国家级重点技工学校,是集职业需求预测.职业技能培训.职业技能鉴定.就业指导为一体的多层次.多元化的高级技术学校.经过充分论证,北京一轻高级技工学校决定建设网络实训室,为培养网络技术人才提供基础设施.学校设定了网络实训室的建设目标:第一要能够拟真实环境,为学生提供适应市场需要的实战性.模块化.项目化.情景化的学习资源:第二要建成高水平的综合网络实验室,成为满足不同层次教学需求的面向全校学生开放的计算机网络技术实验基地和人才培养基地. 为实训室搭建"好网络&