/** Train the generator by adding the sourceText */
  @Override
  public void train(String sourceText) {
    // TODO: Implement this method

    String splitOn = "[\\s.]+";
    String[] words = sourceText.split(splitOn);
    String prev = starter;
    for (String word : words) {
      ListNode tomodify = null;
      ListIterator<ListNode> iter = wordList.listIterator();
      while (iter.hasNext()) {
        ListNode node = iter.next();
        if (node.getWord().equals(prev)) {
          tomodify = node;
          break;
        }
      }
      if (tomodify == null) {
        tomodify = new ListNode(prev);
        wordList.add(tomodify);
      }

      // add w to the targeted ListNode
      tomodify.addNextWord(word);
      prev = word;
    }
  }
 /*
 Markov Text Generation depends on an initial source text to mimic.
 This method takes in String to train the Markov Text Generator.
 */
 @Override
 public void train(String sourceText) {
   // TODO: Implement this method
   if (sourceText == null || sourceText.length() == 0) {
     return;
   }
   String[] words = sourceText.split("[ ]+"); // 注意test cases中,words之间可能有多个空格
   starter = words[0];
   for (int i = 1; i < words.length; i++) {
     String crtWord = words[i];
     ListNode prevNode = isExist(words[i - 1], wordList);
     if (prevNode == null) {
       prevNode = new ListNode(words[i - 1]);
       wordList.add(prevNode);
     }
     prevNode.addNextWord(crtWord);
   }
   // setup the "starter" word and to make sure the last word also points to the start word.
   ListNode prevNode = isExist(words[words.length - 1], wordList);
   if (prevNode == null) {
     prevNode = new ListNode(words[words.length - 1]);
     wordList.add(prevNode);
   }
   prevNode.addNextWord(starter);
 }
 private ListNode findNode(String key) {
   for (ListNode n : wordList) {
     if (n.getWord().equals(key)) {
       return n;
     }
   }
   return null;
 }
 // Can be helpful for debugging
 @Override
 public String toString() {
   String toReturn = "";
   for (ListNode n : wordList) {
     toReturn += n.toString();
   }
   return toReturn;
 }
 // helper function
 private ListNode isExist(String crtWord, List<ListNode> wordList) {
   int size = wordList.size();
   for (int i = 0; i < size; i++) {
     ListNode node = wordList.get(i);
     if (node.getWord().equals(crtWord)) {
       return node;
     }
   }
   return null;
 }
  /** Generate the number of words requested. */
  @Override
  public String generateText(int numWords) {
    // TODO: Implement this method
    if (wordList.size() == 0) {
      return "";
    }
    String text = "";
    String current = starter;

    for (int i = 0; i < numWords; i++) {
      ListNode curnode = findNode(current);
      if (curnode == null) {
        curnode = findNode(starter);
      }
      String nexttext = curnode.getRandomNextWord(rnGenerator);
      text = text + nexttext + " ";
      current = nexttext;
    }
    return text;
  }
 /*
 The goal of Markov Text Generation is to be able to generate text which resembles the source in a reasonable way.
 The method generateText returns such text as a String of words, the length of which is determined by numWords.
 */
 @Override
 public String generateText(int numWords) {
   // TODO: Implement this method
   if (numWords < 0) {
     throw new IllegalArgumentException("Illegal Argument");
   }
   if (numWords == 0) {
     return "";
   }
   StringBuilder sb = new StringBuilder();
   String crtWord = starter;
   sb.append(crtWord + " ");
   numWords--; // 先减去starter word占据的一个
   while (numWords-- > 0) {
     ListNode node = isExist(crtWord, wordList);
     String next = node.getRandomNextWord(rnGenerator);
     sb.append(next + " ");
     crtWord = next;
   }
   return sb.toString();
 }