需求分析
- 程序能够从文件中读取文章,且具备学习能力
- 建立前后缀之间的关系
- 控制文章输出的篇幅(字数)
- 随机生成文章
做题思路(设计思路&解决问题)
一、程序且具备学习能力
结合参考文章的思路:利用连续两个词构成的前缀来选择作为后缀的一个词
设置w1和w2为文本的前两个词
输出w1和w2
循环:
随机地选出w3,它是文本中w1w2的后缀中的一个
打印w3
把w1和w2分别换成w2和w3
重复循环
"this is" -> ["a"]"is a" -> ["good", "dog"]"a dog" -> ["and", "where"]"dog and" -> ["it", "this"]
由此,第一个问题和难点来了,如何做前缀和后缀,用什么方式去做?
解决过程(一):
- 首先,在课程开始的时候我在追看这位老兄写的博客,曾经关于封装,继承,多态的理解他给了我很大帮助.
在Java提高篇(二三)后讲到了Map的实现,产生key-value键对值,将键映射到值的对象。
这样就满足了根据w1w2选择出w3。 - 然后,决定用List<> 来作为前缀的容器。
- 首先,在课程开始的时候我在追看这位老兄写的博客,曾经关于封装,继承,多态的理解他给了我很大帮助.
解决过程(二):
//前缀用一个类来表示:public class Front//首先得有保存前缀的基本属性:public List<String> pref; //前缀保存的两个词,w1,w2按顺序存入//对于一篇文章,程序每读一个单词,程序就会重复以下步骤:add(word);private void add(String word) { List<String> suf = stateTable.get(prefix); if(suf == null){ suf = new ArrayList<String>(); stateTable.put(new Prefix(prefix),suf); //Map<Front,List<String>> stateTable = new HashMap<Front,List<String>>();} Front.pref.remove(0); Front.pref.add(word); }
二、随机生成文章和控制输出篇幅
- 已经建立了前后缀之间的映射关系,只需要建立循环Num次
FileWriter fw = new FileWriter(*.txt); for(int i=0; i<Num; i++){ List<String> suf = stateTable.get(prefix); int r = Math.abs(random.nextInt() % suf.size()); String word = suf.get(r); System.out.print(word+" "); if(word.equals(".")){fw.write("\n");}elsefw.write(word+" "); prefix.pref.remove(0); prefix.pref.add(word); } fw.close;
三、程序读取文章
- 这个确实不是什么大问题,解决过程如下:
FileInputStream fis = new FileInputStream(new File("C:/*/*.txt"));Scanner scanner = new Scanner(InputStream in); while(scanner.hasNext()){ add(scanner.next()); }
关键代码解释(通过注释解释)
public class Chain { static final int NPREF = 2; //size of prefix //因为是利用两个词来构成前缀,所以定义了Front的构造函数Pront(int a,String b),所以这里a=2;b一开始为"\n" static final String NOWORD = "\n"; Map<Front,List<String>> stateTable = new HashMap<Front,List<String>>(); Front prefix = new Front(NPREF,NOWORD); Random random = new Random(); //用于产生随机数 public void build(InputStream in) throws Exception { Scanner scanner = new Scanner(in); //读取文件while(scanner.hasNext()){ add(scanner.next()); } add(NOWORD); } //add方法是为了建立前缀的库,以及生成前后缀之间的映射private void add(String word) { List<String> suf = stateTable.get(prefix); if(suf == null){ suf = new ArrayList<String>(); stateTable.put(new Prefix(prefix),suf); } suf.add(word); prefix.pref.remove(0); //实现前缀 w1w2 转变为 w2w3;先调用List的remove方法删除w2,然后加入w3与w2组成新的后缀prefix.pref.add(word); } //根据篇幅数进行循环public void generate() {FileWriter fw = new FileWriter(args[1]); prefix = new Prefix(NPREF,NOWORD); for(int i=0; i<args[0]; i++){ List<String> suf = stateTable.get(prefix); int r = Math.abs(random.nextInt() % suf.size()); //根据w1w2来产生w3String word = suf.get(r); if(word.equals(NOWORD)){ break; } System.out.print(word+" "); fw.write(word+" "); prefix.pref.remove(0); prefix.pref.add(word); }fw.close; } }
题目总结
- 这次的题目很难,这真的很打脑壳,有很多知识都是课下自己补充的,在一些思路和方法上也借鉴了些其他人的,导致这次的结对编程很尴尬。
- 这个程序只是做到了根据一些文章来写一篇文章,生成的文章还些许的语法错误,也没能很好处理标点的问题。
- 一开始看到要求中“避免环”,嘎住了,这个东西也没能解决。
- 程序执行效率分析未能完成,因为做出以上的东西对现在的我来说较为难了
- 总之,每次的结对编程都是一次成长的过程,当然还有折磨...这让我清楚的认识到“当自己的才华撑不起自己的野心的时候,静下来学习吧”