2014-02-22 31 views
1

我的代碼拋出了一個我從未見過的錯誤。嘿!我想我正在學習;)無論如何,我做了一些閱讀,並且通常當迭代的列表被修改爲中間迭代時引發這個錯誤。但是,我很確定我沒有修改它。在分區()上拋出錯誤時,如果我沒有爲updateCurrentList()中的currentList分配新值(通過註釋代碼),程序不會再拋出錯誤。這兩個函數在我的play()方法中被一個接一個地調用,但是當進行更改時,列表迭代應該完成。我錯過了什麼?我是否必須以某種方式關閉迭代器?無法弄清楚什麼是觸發「java.util.ConcurrentModificationException」

package hangman; 
import java.io.*; 
import java.util.*; 
import javax.swing.JOptionPane; 

public class Hangman { 
    private Map<String, List<String>> wordPartitions; // groups words according to positions of guessed letter 
    private List<String> currentList; // remaining possible words that fit the information given so far 
    Set<Character> wrongGuesses; // holds all the "wrong" guesses so far 
    StringBuilder guessString; // current state of the word being guessed 
    String justHyphens; // for checking whether a guess was "wrong" 

    // initialize fields 
    // currentList should contain all (and only) words of length wordLength 

// justHyphens and guessString should consist of wordLength hyphens 
public Hangman(int wordLength) throws FileNotFoundException { 
    this.currentList = new ArrayList<String>(); 
    addWords(wordLength); 
    wrongGuesses = new HashSet(); 

    for(int i = 0; i < wordLength; i++) { 
     justHyphens += "-"; 
    } 
    guessString = new StringBuilder(); 
    wordPartitions = new HashMap(); 
} 

private void addWords(int wordLength) throws FileNotFoundException { 
    Scanner words = new Scanner(new File("lexicon.txt")); 
    String word = ""; 

    while(words.hasNext()) { 
     word = words.next(); 
     if (word.length() == wordLength) { 
      currentList.add(word); 
     } 
    } 
} 

// main loop 
public void play() { 
    char choice; 

    do { 
     choice = getUserChoice(); 
     partition(choice); 
     updateCurrentList(choice); 
    } while (!gameOver()); 
     endMessage(); 
} 

// display the guessString and the missed guesses 
// and get the next guess 
private char getUserChoice() { 
    //generate a string from the incorrect choices char list 
    String wrong = ""; 
    char letter; 

    if(!wrongGuesses.isEmpty()) { 
     Iterator<Character> letters = wrongGuesses.iterator(); 
     letter = letters.next(); 

     while(letters.hasNext()) { 
      letter = letters.next(); 
      wrong += ", " + letter; 
     } 
    } 

    String letterStr = JOptionPane.showInputDialog("Incorrect choices: "+ wrong +"\n Tested letters: "+ guessString.toString() +"\nplease input a letter."); 
    return letterStr.charAt(0); 
} 


// use wordPartitions to partition currentList using 
// keys returned by getPartitionKey() 
private void partition(char choice) { 

    String word = ""; 
    String key = ""; 
    List<String> tempList = new ArrayList<String>(); 

    Iterator<String> words = currentList.iterator(); 
    //Generate a key for each word and add to appropriate arraylist within map. 
    while(words.hasNext()) { 
     word = words.next(); 
     key = getPartitionKey(word, choice); 

     if(wordPartitions.containsKey(key)) { 
      tempList = wordPartitions.get(key); 
      tempList.add(word); 
      wordPartitions.put(key, tempList); 
     } else { 
      tempList.clear(); 
      tempList.add(word); 
      wordPartitions.put(key, new ArrayList<String>());     
     }    
    } 
} 

// update currentList to be a copy of the longest partition 
// if choice was "wrong", add choice to wrongGuesses 
// if choice was "right", update guessString 
private void updateCurrentList(char choice) {   
    String key = findLongestList(); 

    currentList = wordPartitions.get(key); 

    if(key.equals(justHyphens)) { 
     wrongGuesses.add(choice); 
    } else { 
     addLetterToGuessString(guessString, choice, key); 
    } 
} 

private String findLongestList() { 
    Set<String> keySet = wordPartitions.keySet(); 
    Iterator<String> keys = keySet.iterator(); 
    String maxKey = ""; 
    int maxKeyLength = 0; 
    List<String> tempList; 
    String tempKey = ""; 

    while(keys.hasNext()) { 
     tempKey = keys.next(); 
     tempList = wordPartitions.get(tempKey); 

     if(tempList.size() > maxKeyLength) { 
      maxKeyLength = tempList.size(); 
      maxKey = tempKey; 
     } 
    } 

    return maxKey; 
} 

// checks for end of game 
private boolean gameOver() { 
    return false; 
} 

// display the guessString and the missed guesses 
// and print "Congratulations!" 
private void endMessage() { 
    JOptionPane.showMessageDialog(null, "Congrats, yo!"); 
} 

// returns string with '-' in place of each 
// letter that is NOT the guessed letter 
private String getPartitionKey(String s, char c) { 
    String word = ""; 
    String letter = Character.toString(c); 
    for(int i = 0; i < s.length(); i++) { 
     if(s.charAt(i) == c) { 
      word += letter; 
     } else { 
      word += "-"; 
     } 
    } 

    return word; 
} 
// update guessString with the guessed letter 
private void addLetterToGuessString(StringBuilder guessString, char letter, String key) { 
    for(int i = 0; i < key.length(); i++) { 
     if(key.charAt(i) != '-') { 
      guessString.setCharAt(i, key.charAt(i)); 
     } 
    } 
} 

}

+0

這是你提到的play()方法嗎? – donfuxx

+1

提供運行或激發這些方法的代碼。 – RMachnik

+0

謝謝!在代碼示例的頂部添加了該代碼。 –

回答

2

的問題是,你正在修改的集合,而你是遍歷它。

集合是currentList,您在partition()中迭代它。您可以修改它,當你添加一個詞來tempList這裏:

key = getPartitionKey(word, choice); 

if(wordPartitions.containsKey(key)) { 
    tempList = wordPartitions.get(key); 
    tempList.add(word); 
    wordPartitions.put(key, tempList); 
} else { 

爲什麼?因爲以前你從play()稱爲updateCurrentList()

do { 
    choice = getUserChoice(); 
    partition(choice); 
    updateCurrentList(choice); 
} while (!gameOver()); 

你更新currentList

String key = findLongestList(); 

currentList = wordPartitions.get(key); 

所以,如果getPartitionKey(word, choice)返回key相同以前findLongestList()返回鍵,currentList將是與tempList相同,因此您將修改正在迭代的集合。

解決方案?如果tempListcurrentList相同,則不要將單詞添加到該單詞中(根據定義它已經包含單詞)。所以,你可以重寫你的if-else那樣(我刪除了一些無用的代碼):

if(wordPartitions.containsKey(key)) { 
    tempList = wordPartitions.get(key); 
} else { 
    wordPartitions.put(key, new ArrayList<String>());     
} 

if (tempList!=currentList) { 
    tempList.add(word); 
} 
相關問題