和我一起开发Android应用(四)——拓词算法分析和“悦词”词库解析

  今天我们要部分实现背单词功能,在开始正题之前,还是附上背单词软件的下载链接:http://apk.91.com/Soft/Android/com.carlos.yueci-4.html

最近实验室有了任务,时间会紧些,因此这个项目要加快进度了。

  首先把我在系列二中的功能分析拷贝过来:

  功能2、背单词。

    实现方法:这里要用到第二个数据库,背单词的词库。我们需要一个存放单词的TXT文件,通过解析这个TXT文件,将要背的单词解析并存进数据库中,然后根据一定的规           律弹出单词。

  所用到的技术:

    1)数据库,同前面的数据库技术相似;

    2)对TXT文件中的单词进行解析,字符串解析函数;

    3)单词状态机,设计一定的算法,按照一定的规律弹出单词,并进行背词操作。(这个确实挺麻烦)

    4)文件浏览,做一个简易的文件浏览器,用于浏览SD卡中的单词源文件txt,然后导入词库。这个属于比较单独的一个功能。

  今天的主要工作是实现数据库,解析txt单词本,然后篇幅允许的话会分析一下拓词软件的背单词算法。

一、数据库部分。

  为了避免和词典功能对应的数据库相互冲突,我们重新建一个DatabaseHelper,而不是采用在一个数据库中创建多个表的方法,这样操作起来互不干扰,不容易出错。

这里创建的数据库用来记录所需要背的单词、释义,以及背词次数,答错次数,掌握程度,等等。这里我借鉴了拓词的“掌握程度”的思路,利用掌握程度来决定单词出现的频度。

  首先创建一个DatabaseHelper子类:

package com.carlos.database;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;

public class DataBaseHelper extends SQLiteOpenHelper{

    public Context mContext=null;
    public String tableName=null;
    public static int VERSION=1;

    public SQLiteDatabase dbR=null;
    public SQLiteDatabase dbW=null;
    public DataBaseHelper(Context context, String name, CursorFactory factory,
            int version) {
        super(context, name, factory, version);
        // TODO Auto-generated constructor stub
        mContext=context;
        tableName=name;
        dbR=this.getReadableDatabase();
        dbW=this.getWritableDatabase();
    }

    public DataBaseHelper(Context context, String name, CursorFactory factory){
        this(context,name,factory,VERSION);
        mContext=context;
        tableName=name;
    }

    public DataBaseHelper(Context context, String name){
        this(context,name,null);
        mContext=context;
        tableName=name;
    };

    @Override
    public void onCreate(SQLiteDatabase db) {
        // TODO Auto-generated method stub
        db.execSQL("create table glossary(word text,interpret text," +
                "right int,wrong int,grasp int,learned int)");

    }

    @Override
    public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
        // TODO Auto-generated method stub

    }

    /**
     *
     * @param word
     * @param interpret
     * @param overWrite  是否覆写原有数据
     * @return
     */
    public boolean insertWordInfoToDataBase(String word,String interpret,boolean overWrite){

        Cursor cursor=null;

        cursor=    dbR.query(tableName, new String[]{"word"}, "word=?", new String[]{word},null, null, "word");
        if(cursor.moveToNext()){
            if(overWrite){
                ContentValues values=new ContentValues();
                values.put("interpret", interpret);
                values.put("right", 0);
                values.put("wrong",0);
                values.put("grasp",0);
                values.put("learned", 0);

                dbW.update(tableName, values, "word=?", new String[]{word});
                cursor.close();
                return true;
            }else{
                cursor.close();
                return false;
            }
        }else{

            ContentValues values=new ContentValues();
            values.put("word", word);
            values.put("interpret", interpret);
            values.put("right", 0);
            values.put("wrong",0);
            values.put("grasp",0);
            values.put("learned", 0);
            dbW.insert(tableName, null, values);
            cursor.close();
            return true;
        }

    }

}

db.execSQL("create table glossary(word text,interpret text,right int,wrong int,grasp int,learned int)");

word: 单词;

interpret:  翻译;

right: 答对次数;

wrong: 答错次数;

grasp: 掌握程度;

learned: 用于标识该单词是否已经背过

另外这里添加了一个方法,外部可以调用该方法insertWordInfoToDataBase,把单词和其对应的翻译导入数据库,isOverWrite用来设置是否覆盖数据库中原有的单词信息。

然后在使用数据库时和之前词典功能中类似,实例化一个DatabaseHelper子类对象,然后获得readableDatabase和writableDatabase 即可执行增删改查等操作。

  二、解析单词TXT文本。

  可能朋友们一直有个疑惑,到底单词是以怎样的形式导入到词库中的?其实用txt导入是我的一个巧合性的选择,因为正好我背单词时使用的是一个PDF的单词表,于是我就把这个PDF转换成txt,然后想办法对这个txt进行解析,txt中的内容格式如下:

hello  int.你好,哈喽          beat  v.打败,战胜happy    a.欢乐幸福

number  n.数字                alphabetical  a.按字母表顺序的      wind  n.风

每一行的单词可以是多个,单词和该单词的释义之间必须要有一个或多个空格。

如何解析呢?基本的思路,就是要把单词和释义“分离”开来,并且要一一对应。这里我首先想到使用正则表达式进行匹配,基本的思路如下:

1、首先在一行单词表中把所有的单词找出来,存放在一个ArrayList<String >数组中,使用正则表达式  “[a-zA-Z]+[ ]+”  [a-zA-Z]+ 表示有一个或多个英文字母,后面紧跟着一个或多个空格[ ]+。

hello  int.你好,哈喽          beat  v.打败,战胜happy    a.欢乐幸福

这样可以就可以提出三个单词,hello ,beat, happy

2、然后把一行字符串中所有的单词位置替换成一个标记——  <S%%E>,那么字符串将会变成:注意这个标记可以自己设计成其它的,但最好特殊一点!

<S%%E>int.你好,哈喽          <S%%E>v.打败,战胜<S%%E>a.欢乐幸福

3、然后在字符串尾再加上一个标记:<S%%E>

<S%%E>int.你好,哈喽          <S%%E>v.打败,战胜<S%%E>a.欢乐幸福<S%%E>

4、这样我们可以发现在%E> 和<S%之间的内容肯定是翻译,那么我们用一个正则表达式%E>[^<S%%E>]+<S% 把它匹配出来,[^<S%%E>]+ 的含义是%E>和<%S之间不能有:<S%%E>,这样就可以避免一次就把多个翻译匹配出来。

%E>int.你好,哈喽          <S%

%E>v.打败,战胜<S%

%E>a.欢乐幸福<S%

然后取第4到倒数第4个字符之间的字符创建字符串就可去除标记,获得最终的翻译:

int.你好,哈喽

v.打败,战胜

a.欢乐幸福

这样我们把单词和其对应的翻译就获得了,然后把其insert到前面创建的数据库就可以把单词信息导入到数据库了:,这里需要用到上面提到的数据库中的insertWordToDatabase方法。

这里我把这个方法封装到一个类中了:

package com.carlos.text_parser;

import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

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

import com.carlos.database.DataBaseHelper;

public class WordListParser {
    public DataBaseHelper dbHelper=null;
    public Context context=null;
    public String tableName=null;
    public WordListParser(){

    }

    public WordListParser(Context context, String tableName) {
        this.context=context;
        this.tableName=tableName;
        dbHelper=new DataBaseHelper(context, tableName);
    }

    public void parse(String lineStr){
        int countWord=0;
        int countInterpret=0;
        int count=0;
        String strInterpret="";
        String str="";
        char[] charArray=null;
        Pattern patternWord=Pattern.compile("[a-zA-Z]+[ ]+");
                      //"%>[^<%%>]*<%"
        Pattern patternInterpret=Pattern.compile("%E>[^<S%%E>]+<S%");
        Matcher matcherWord=patternWord.matcher(lineStr);
        Matcher matcherInterpret=null;
        ArrayList<String> wordList=new ArrayList<String>();
        ArrayList<String> interpretList=new ArrayList<String>();

        while(matcherWord.find()){
            str=matcherWord.group();
            charArray=str.toCharArray();
            if(charArray.length>0 && (charArray[0]>=‘A‘&& charArray[0]<=‘Z‘ )){
                charArray[0]+=(‘a‘-‘A‘);
                str=new String(charArray,0,charArray.length);     //首字母去掉大写
            }
            wordList.add(str.trim());
        }
        if(wordList.size()<=0)
            return;
        matcherWord.reset(lineStr);
        if(matcherWord.find()){
            strInterpret=matcherWord.replaceAll("<S%%E>");
        }
        strInterpret+="<S%%E>";

        matcherInterpret=patternInterpret.matcher(strInterpret);
        while(matcherInterpret.find()){
            str=matcherInterpret.group();
            interpretList.add(new String(str.toCharArray(),3,str.length()-6));
        }
        countWord=wordList.size();
        countInterpret=interpretList.size();
        count=countWord>countInterpret?countInterpret:countWord;
        for(int i=0;i<count;i++){
            dbHelper.insertWordInfoToDataBase(wordList.get(i), interpretList.get(i), true);
        }
    }

//    public boolean isOfAnWord(int index,char[] str){
//        int i=index;
//        for( ;i<str.length;i++  ){
//            if(isAlpha(str[i])==false)
//                break;
//        }
//        if(i==index)
//            return false;
//        if(i>=str.length)
//            return true;
//        if(str[i]==‘.‘)
//            return false;
//        return true;
//
//    }
//
//
//    public boolean isAlpha(char ch){
//        if((ch>=‘A‘&&ch<=‘Z‘) ||(ch>=‘a‘&&ch<=‘z‘)){
//            return true;
//        }
//        else
//            return false;
//    }
//
//
//    public boolean isChinese(char ch){
//        if(ch>129)
//            return true;
//        else
//            return false;
//    }

}

  三、拓词算法分析

  诚然,“悦词”软件在背单词的思路上是参考了拓词,但因为做这款应用的初衷是方便我背单词,所以只保留了背单词算法中最核心的部分。下面我介绍下基本思路:

  这里采用了掌握程度的思路,采用了状态机的模式:

使用了状态变量:

1、process:每一天总的学习进度:对应的状态值有
public final static int GRASP_89=8;     //89级掌握程度,属于复习背过的单词的阶段,下同
 public final static int GRASP_67=6;
 public final static int GRASP_45=4;
 public final static int GRASP_23=2;
 public final static int GRASP_01=0;
 public final static int LEARN_NEW_WORD=10;     //当天学习新单词的阶段

2、processLearnNewWord:学习新单词阶段对应的子进度,对应的状态有:

public final static int STEP_1_NEWWORD1=0;   //阶段1,学习新单词10个
 public final static int STEP_2_REVIEW_20=1;    //阶段2,复习20个旧的单词
 public final static int STEP_3_NEWWORD2=2;    //阶段3,学习新单词10个左右
 public final static int STEP_4_REVIEW_6=3;        //阶段4,复习约6个旧单词

    3、wordCount:某一阶段内已经背的单词数

新的一天开始后,应用会自动将process重置为GRASP_89(如何实现这一点后面会讲),开始复习背过的单词,先背掌握程度高的,然后掌握程度逐渐降低。89掌握程度约背全部89掌握程度的20%,67掌握程度背全部67掌握程度的45%,45掌握程60%,23 70% ,01 85%,这个概率可以根据个人理解改变,当完成所有旧单词的复习过程后,进入新单词学习阶段。

在新单词学习阶段,首先背十个新单词,然后转为复习01掌握程度的20个左右的单词,然后再被10个新单词,然后再复习01掌握程度的6个左右的单词,然后进入下一轮循环。新单词阶段一直循环上述四个阶段,直至完成当天的背词任务。

对于出错单词的处理,这里我添加了一个队列LinkedList<WordInfo> wrongWordList ,用于存放背错的单词。当被错的单词数目达到一定值后,状态机会自动进入背错词状态,程序会把前一段时间被错的单词顺序弹出来,直至队列变空,然后单词状态机回到原来的背词状态。  出错状态用状态变量processWrong控制,该变量的优先级要高于process,当processWrong为true时,状态机将优先进入弹错词状态,当processWrong变回wrong,状态机再执行原来的process.

以上就是基本思路,下面将该思路封装成一个类WordBox

package com.carlos.wordcontainer;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
import java.util.Stack;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.carlos.database.DataBaseHelper;

public class WordBox {
    public Context context=null;
    public String tableName=null;
    private DataBaseHelper dbHelper=null;
    private SQLiteDatabase dbR=null,dbW=null;

    public final static int GRASP_89=8;
    public final static int GRASP_67=6;
    public final static int GRASP_45=4;
    public final static int GRASP_23=2;
    public final static int GRASP_01=0;
    public final static int LEARN_NEW_WORD=10;
    public final static int LEARNED=1;
    public final static int UNLEARNED=0;

    public static int process=GRASP_89;    //总学习进度控制变量
    public static int wordCount=0;         //在某一复习阶段背的单词数
    public static boolean processWrong=false;        //是否要开始背错误的单词

    public final static int STEP_1_NEWWORD1=0;
    public final static int STEP_2_REVIEW_20=1;
    public final static int STEP_3_NEWWORD2=2;
    public final static int STEP_4_REVIEW_6=3;
    public static int processLearnNewWord=STEP_1_NEWWORD1;

    public LinkedList<WordInfo> wrongWordList=null;
    public Random rand=null;

    public WordBox(Context context,String tableName){
        this.context=context;
        this.tableName=tableName;
        dbHelper=new DataBaseHelper(context, tableName);
        dbR=dbHelper.getReadableDatabase();
        dbW=dbHelper.getWritableDatabase();
        wrongWordList=new LinkedList<WordInfo>();
        rand=new Random();
    }

    @Override
    protected void finalize() throws Throwable {
        // TODO Auto-generated method stub
        dbR.close();
        dbW.close();
        dbHelper.close();
        super.finalize();
    }

    public void removeWordFromDatabase(String word){
        dbW.delete(tableName, "word=?", new String[]{word});
    }

    /**
     * 多个条件查找Where子句时需要用and 或or连接
     * @param grasp
     * @param learned
     * @return
     */

    public int getWordCountByGrasp(int grasp ,int learned){       //获得数据库中某个掌握程度的单词的个数
        Cursor cursor=dbR.query(tableName, new String[]{"word"}, "grasp=? and learned=?", new String[]{grasp+"",learned+""}, null, null, null);
        int count=cursor.getCount();
        cursor.close();
        return count;
    }

    public int getTotalLearnProgress(){
        int learnCount=0;
        int totalCount=0;
        Cursor cursor=dbR.query(tableName, new String[]{"word"}, "grasp=? or grasp=? or grasp=? or grasp=? or grasp=? or grasp=? or grasp=? or grasp=?", new String[]{"3","4","5","6","7","8","9","10"}, null, null, null);
        learnCount=cursor.getCount();

        Cursor cursorTotal=dbR.query(tableName, new String[]{"word"}, "word like?", new String[]{"%"}, null, null, null);
        totalCount=cursorTotal.getCount();

        cursor.close();
        cursorTotal.close();
        if(totalCount==0){
            return 0;
        }
        return  (int)(((float)learnCount/(float)totalCount)*100);
    }

    public int getWordCountOfUnlearned(){
        Cursor cursorTotal=dbR.query(tableName, new String[]{"word"}, "word like?", new String[]{"%"}, null, null, null);
        int totalCount=cursorTotal.getCount();
        Cursor cursor=dbR.query(tableName, new String[]{"word"}, "grasp=? or grasp=? or grasp=? or grasp=? or grasp=? or grasp=? or grasp=? or grasp=?", new String[]{"3","4","5","6","7","8","9","10"}, null, null, null);
        int learnCount=cursor.getCount();
        cursor.close();
        cursorTotal.close();
        return totalCount-learnCount;
    }

    public WordInfo getWordByGraspByRandom(int fromGrasp,int toGrasp,int learned){    //从数据库中随机取出某个特定掌握程度区间的单词,加learned是区别学习程度为0的学过得和没学过的
        int totalCount=0,temp=0;
        ArrayList<Integer> graspsNotEmpty=new ArrayList<Integer>();
        for(int i=fromGrasp; i<=toGrasp;i++){
            temp=getWordCountByGrasp(i,learned);  //这说明给定掌握程度范围内没有单词
            totalCount+=temp;
            if(temp>0)
                graspsNotEmpty.add(i);  //把对应的grasp添加
        }
        if(totalCount<=0){        //这里应该在外部添加判断空的表不能够进来
            return null;
        }

        int length=graspsNotEmpty.size();
        if(length<=0)
            return null;       //在有数据的掌握程度中随机找出一个单词来
        int graspInt=graspsNotEmpty.get(rand.nextInt(length));     //随机确定一个掌握程度
        int count=getWordCountByGrasp(graspInt, learned);          //确定该掌握程度单词数,获得Cursor对象,利用move方法进行随机移动
        int index=rand.nextInt(count)+1;
        Cursor cursor=dbR.query(tableName, new String[]{"word","interpret","right","wrong","grasp"},"grasp=? and learned=?" , new String[]{graspInt+"",learned+""}, null, null, null);
        cursor.move(index);
        String word=cursor.getString(cursor.getColumnIndex("word"));
        String interpret=cursor.getString(cursor.getColumnIndex("interpret"));
        int wrong=cursor.getInt(cursor.getColumnIndex("wrong"));
        int right=cursor.getInt(cursor.getColumnIndex("right"));
        int grasp=cursor.getInt(cursor.getColumnIndex("grasp"));
        cursor.close();
        return new WordInfo(word, interpret, wrong, right, grasp);
    }

    /**
     * 随机从词库中找一个单词!
     */
    public static int lastGetIndex=0;

    public WordInfo getWordByRandom(){
        int count=0;
        Cursor cursor=dbR.query(tableName, new String[]{"word","interpret","right","wrong","grasp"},"word like?" ,
                new String[]{"%"}, null, null, null);
        if((count=cursor.getCount())<=0){
            cursor.close();
            return null;
        }

        int i=0;
        int index=0;
        while(i<6){
            index=rand.nextInt(count)+1;
            if(index!=lastGetIndex)
                break;
            i++;
        }

        lastGetIndex=index;
        cursor.move(index);
        String word=cursor.getString(cursor.getColumnIndex("word"));
        String interpret=cursor.getString(cursor.getColumnIndex("interpret"));
        int wrong=cursor.getInt(cursor.getColumnIndex("wrong"));
        int right=cursor.getInt(cursor.getColumnIndex("right"));
        int grasp=cursor.getInt(cursor.getColumnIndex("grasp"));
        cursor.close();
        return new WordInfo(word, interpret, wrong, right, grasp);
    }

    String[] logProcess=new String[]{"G01","","G23","","G45","","G67","","G89","","NEW WORD"};
    String[] logLearn=new String[]{"NEW1","REVIEW20","NEW2","REVIEW6"};

    //外部接口,点击事件后获得单词
    public WordInfo popWord(){
        WordInfo wordInfo=null;

        /**
         * 打印参数信息
         */

        if(processWrong){
            return getWrongWord();
        }
        switch(process){
            case GRASP_89:{

                if((wordInfo=getWordByAccurateGrasp(GRASP_89, GRASP_67,0.1))!=null)
                    return wordInfo;
            }
            case GRASP_67:{
                if((wordInfo=getWordByAccurateGrasp(GRASP_67, GRASP_45,0.3))!=null)
                    return wordInfo;
            }
            case GRASP_45:{
                if((wordInfo=getWordByAccurateGrasp( GRASP_45,GRASP_23,0.4))!=null)
                    return wordInfo;
            }
            case GRASP_23:{
                if((wordInfo=getWordByAccurateGrasp(GRASP_23, GRASP_01,0.5))!=null)
                    return wordInfo;
            }
            case GRASP_01:{
                if((wordInfo=getWordByAccurateGrasp(GRASP_01,LEARN_NEW_WORD,0.5))!=null)
                    return wordInfo;
            }
            case LEARN_NEW_WORD:{
                return learnNewWord();
            }
            default:
                break;

        }
        return null;
    }

    //外部敲击后反馈回来的函数
    public void feedBack(WordInfo wordInfo,boolean isRight){
        if(wordInfo==null)
            return;           //对可能出现的空指针异常进行处理

        String word=wordInfo.getWord();
        int right=wordInfo.getRight();
        int wrong=wordInfo.getWrong();
        int graspInt=0;
        if(isRight){
            right++;
        }else{
            wrong++;      //更新答对答错次数
        }
        if(right-2*wrong<0){
            graspInt=0;
        }else if(right-2*wrong>10){
            graspInt=10;
        }else{
            graspInt=right-2*wrong;
        }

        //更新数据库
        ContentValues values=new ContentValues();
        //更新应该只会更新添加的项吧,暂时这么处理
        values.put("right", right);
        values.put("wrong",wrong);
        values.put("grasp",graspInt);
        values.put("learned", LEARNED);
        dbW.update(tableName, values, "word=?", new String[]{word});

        //若出错,将数据存在出错队列中
        if(isRight==false){
            wordInfo.setRight(right);
            wordInfo.setWrong(wrong);
            wordInfo.setGrasp(graspInt);
            wrongWordList.offer(wordInfo);
        }

    }

    //新词学习阶段调用的函数
    public WordInfo learnNewWord(){
        //这里设置一个彩蛋
        WordInfo wordInfo=null;

        switch(processLearnNewWord){
            case STEP_1_NEWWORD1:{
                if((wordInfo=getWordByGraspByRandom(GRASP_01,GRASP_01,UNLEARNED ))==null
                        || wordCount>rand.nextInt(3)+9 ){
                    processLearnNewWord=STEP_2_REVIEW_20;
                    wordCount=0;

                    //这里表示所有的词都已经学完了
                    if(getWordCountByGrasp(GRASP_01, UNLEARNED)<=0){
                        process=GRASP_89;
                    }
                }else{
                    wordCount++;
                    return wordInfo;
                }
            }
            case STEP_2_REVIEW_20:{
                if((wordInfo=getWordByGraspByRandom(0,2, LEARNED))==null){
                    processLearnNewWord=STEP_3_NEWWORD2;
                    wordCount=0;
                }else{
                    wordCount++;
                    if(wordCount>rand.nextInt(3)+19){
                        processLearnNewWord=STEP_3_NEWWORD2;
                        wordCount=0;
                        if(wrongWordList.size()>0)
                            processWrong=true;
                    }
                    return wordInfo;
                }
            }
            case STEP_3_NEWWORD2:{
                if((wordInfo=getWordByGraspByRandom(GRASP_01,GRASP_01,UNLEARNED ))==null
                        || wordCount>rand.nextInt(3)+9 ){
                    processLearnNewWord=STEP_4_REVIEW_6;
                    wordCount=0;
                }else{
                    wordCount++;
                    return wordInfo;
                }

            }
            case STEP_4_REVIEW_6:{

                if((wordInfo=getWordByGraspByRandom(0,2, LEARNED))==null){
                    processLearnNewWord=STEP_1_NEWWORD1;
                    wordCount=0;
                    /**
                     * 这里必须返回一个非空值,否则程序将面临空指针异常(会执行default)
                     * 解决这个问题的方法是从数据库中随机取一个单词填坑。
                     */
                    return getWordByRandom();

                }else{
                    wordCount++;
                    if(wordCount>rand.nextInt(3)+5){
                        processLearnNewWord=STEP_1_NEWWORD1;
                        wordCount=0;
                        if(wrongWordList.size()>0)
                            processWrong=true;
                    }
                    return wordInfo;
                }

            }
            default: return null;     

        }

    }

    //复习阶段调用的取词函数
    public WordInfo getWordByAccurateGrasp(int curentGrasp,int nextGrasp,double percent){
        int count=0;
        if((count=getWordCountByGrasp(curentGrasp,LEARNED)+getWordCountByGrasp(curentGrasp+1,LEARNED))<=0 || wordCount>=count*percent){
            process=nextGrasp;
            wordCount=0;
            return null;
        }else{
            wordCount++;

            if(wordCount%(rand.nextInt(2)+19) ==0 && wrongWordList.size()>0 ){  //错误列表中必须有单词
                processWrong=true;
            }
            /**
             * return getWordByGraspByRandom(rand.nextInt(2)+curentGrasp,LEARNED );
             * 这样写会可能返回空值!需要逐个排除
             */
            return getWordByGraspByRandom(curentGrasp,curentGrasp+1, LEARNED);

        }
    }

    //学习错词的函数
    public WordInfo getWrongWord(){  //该函数被调用时,意味着错误词列表中一定有单词
        WordInfo word=null;
        word=wrongWordList.poll();
        if(wrongWordList.size()<=0){
            processWrong=false;    //停止显示错词
        }
        return word;
    }

}

一些细节在代码中都有说明,该对象的调用popWord()获得单词对象WordInfo ,而feedBack用于将背单词的结果(对或错)反馈到数据库中,修改该单词的掌握程度。

还有一些随机获得单词,等等方法,以后在实现背单词UI时会有涉及。若有不清楚之处可以评论

另外给出WordInfo单词信息类:

package com.carlos.wordcontainer;

public class WordInfo{
    public String word;
    public String interpret;
    public int wrong;
    public int right;
    public int grasp;
    public WordInfo(String word, String interpret, int wrong, int right,
            int grasp) {
        super();
        this.word = word;
        this.interpret = interpret;
        this.wrong = wrong;
        this.right = right;
        this.grasp = grasp;
    }
    public String getWord() {
        return word;
    }
    public void setWord(String word) {
        this.word = word;
    }
    public String getInterpret() {
        return interpret;
    }
    public void setInterpret(String interpret) {
        this.interpret = interpret;
    }
    public int getWrong() {
        return wrong;
    }
    public void setWrong(int wrong) {
        this.wrong = wrong;
    }
    public int getRight() {
        return right;
    }
    public void setRight(int right) {
        this.right = right;
    }
    public int getGrasp() {
        return grasp;
    }
    public void setGrasp(int grasp) {
        this.grasp = grasp;
    }

}

OK,这节就讲到这里了,背单词的算法部分已经完成,下一节我们将搭建背单词的UI界面,敬请期待

时间: 2024-10-03 09:16:10

和我一起开发Android应用(四)——拓词算法分析和“悦词”词库解析的相关文章

和我一起开发Android应用(一)——开发一款安卓多功能背单词软件

大家好,很久没有在博客园写过东西.前一段时间尝试学过一段时间cocos2d,但是由于学习资料有限,文档较少,一直难有进展,因此在刚刚过去的三周里,我又回到了我的老本行:java ,Android.在假期里我算是正式开发了我的第一个安卓应用: i背单词.经过三个星期的磕磕绊绊,终于写出一个较稳定的版本,现在这款应用已经成功上架GooglePlay,并且很快会在百度移动应用和安智网上架.当然由于这款软件只是由我个人维护,我也不奢求会有多大的下载量了呵呵,但我想有必要把这短时间开发应用的体会做一个总结

和我一起开发Android应用(三)——“悦词-i背单词”词典功能实现

接上一讲.本节我们把词典功能基本实现,首先上一个效果图,我发现大家比较关心界面方面的东西,我之前写的一个关于QQ界面的项目就很受欢迎,当然我现在能写出远比那个好看的界面.但是我想一个应用最核心的东西不完全在界面,一个好的创意,一个好的后台服务才是成功的关键,这也是我不断学习的方向. 另外我发现在百度搜“悦词背单词91”搜索结果全是我在博客园的博文了...所以我把这个项目在91应用市场的下载地址粘上来吧,十分欢迎大家试用一下,有什么改进的意见请写在下面的评论里!地址:http://apk.91.c

和我一起开发Android应用(二)——“悦词-i背单词”项目功能分析

好几天没有更新了,给关心这个系列的朋友们说声抱歉.今天我们开始第二节,项目功能分析.因为这个背单词软件虽说功能比较简单,但要真正实现起来也挺麻烦的.所以今天我们首先分析一下这个应用的功能,然后逐条慢慢实现. PS:这款应用已经上线91助手,百度移动应用和应用宝,有兴趣下来研究的可以百度搜索“悦词i背单词91”就可找到,我想真正用一下这个应用再看这个教程会有比较直观的理解.好废话不多讲,进入正题. 功能分析: 功能1.查单词. 实现方法:金山词霸开放平台提供了一个开放API,通过Http访问金山词

Cardboard虚拟现实开发初步(四)

Google Cardboard 虚拟现实眼镜开发初步(四) Cardboard SDK for Unity Demo的一些解析 写在前面 自从上次写完这个系列的第三篇,忙了一阵子的项目,忙了一阵子的英语,考完一大波考试之后,终于能继续给大家分享一些开发心得了,这期间有好几个同学给我私信甚至qq我,问我啥时候更新,无奈实在是太忙,只能一拖再拖,我感觉是十分对不起大家的,没能及时更新,这里给大家说个对不起.不过能有这么多人关注我的博客,这也是对我最大的肯定,能得到大家的认可心里十分的高兴,希望大家

ubuntu下搭建android开发环境(四)核心篇安装AndroidStudio、sdk、jdk(by 星空武哥)

转载请标注原创地址:http://blog.csdn.net/lsyz0021/article/details/52215996 所有的软件均在ubuntu 14.04 LTS下测试 ubuntu下搭建android开发环境(一)安装ubuntu系统 ubuntu下搭建android开发环境(二)设置ubuntu的root管理员密码 ubuntu下搭建android开发环境(三)ubuntu安装搜狗输入法 ubuntu下搭建android开发环境(四)核心篇安装AndroidStudio.sdk

Android艺术开发探索第四章——View的工作原理(下)

Android艺术开发探索第四章--View的工作原理(下) 我们上篇BB了这么多,这篇就多多少少要来点实战了,上篇主席叫我多点自己的理解,那我就多点真诚,少点套路了,老司机,开车吧! 我们这一篇就扯一个内容,那就是自定义View 自定义View 自定义View的分类 自定义View的须知 自定义View的实例 自定义View的思想 一.自定义View的分类 自定义View百花齐放,没有什么具体的分类,不过可以从特性大致的分为4类,其实在我看来,就三类,继承原生View,继承View和继承Vie

使用Kotlin开发Android

查看我的全部开源项目[开源实验室] 欢迎加入我的QQ群:[201055521],本博客客户端源码下载[请点击] 摘要 我首先声明我并没有使用Kotlin很长时间,我几乎是在学习的同时写了这些文章的.我并没有尝试任何其它的替 代语言,例如Go和Scala,所以如果你是真的考虑换一种开发语言的话,我建议你去搜索一下其他人对这些 语言的评价. 本文原创,转载请注明地址:http://blog.kymjs.com/ 正文 最近,新了解了一门编程语言,叫做Kotlin.Kotlin是Jetbrains公司

PhoneGap与Jquery Mobile组合开发android应用的配置

PhoneGap与Jquery Mobile结合开发android应用的配置 由于工作需要,用到phonegap与jquery moblie搭配,开发android应用程序. 这些技术自己之前也都没接触过,可以说是压根没听说过,真是感慨,在开发领域,技术日新月异,知识真是永远学不完的.就算是做java开发的,可是细分下来,专业方向还是很多的:自己没有涉及的技术还是太多了,自个需要对单个领域专业点,知识丰富点.做不了全才,那咱做个专才,在如今社会还是必须的. 好了,咱们言归正传: PhoneGap

用 Eclipse 开发 Android 应用程序

转自:http://www.apkbus.com/android-13828-1-1.html 开始之前 本教程介绍如何在 Eclipse 环境中进行 Android 应用程序开发,包括两个示例应用程序.第一个示例是一个基本的应用程序,涉及构建和调试的所有阶段.第二个应用程序示例涉及比较复杂的 Android 特性,包括联系人搜索和 Google Maps 地址查找.要想从本教程获得最大收益,具备移动开发经验会有帮助,但不是必需的.开发 Android 应用程序需要 Java? 编程技能,但是对