0

首謀者ゲームを解決するために作られたプログラムを書いています。プログラムの要点は、すべての可能な解のリストを取得し、正しいものではないすべての推測の後、リストから少なくともその解を与えないものをすべて削除することです。このメソッドは、2 つの文字列 (guess と strFromArray) を比較して、同じ値を取得するかどうかを確認するために作成されます。ただし、エラーが発生し、その理由がわかりません。どんな助けでも大歓迎です。

    Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at Game.shortenTheList(Game.java:88)
at Game.guess(Game.java:76)
at Game.play(Game.java:40)
at Game.main(Game.java:23)


/*
 * Compares the two strings. If they would get the same output, return false. If they would get a different output, return true.
 */
public boolean compare(String guess, String strFromArray, int black, int white)
{
    int white2 = 0;
    int black2 = 0;

    char[] arr1 = guess.toCharArray();
    char[] arr2 = strFromArray.toCharArray();

    for(int i=0; i<guess.length(); i++)
    {
        if(arr1[i] == arr2[i])
        {
            black2 ++;
            arr1[i] = '$';
            arr2[i] = '%';
        }
    }

    for(int i=0; i<guess.length(); i++)
    {
        for(int j=0; j<strFromArray.length(); j++)
        {
            if(arr1[i] == arr2[j])
            {
                white2++;
                arr1[i] = '!';
                arr2[j] = '@';
            }
        }
    }

    if(black == black2 && white == white2)
        return false;

    else
        return true;
}

/*
 * Shortens the list of possible solutions by eliminating everything that wouldn't get at least the given output.
 */
public void shortenTheList(String guess, int black1, int white1)
{
    for (String str : possibleSolutions)
    {
        if(compare(guess, str, black1, white1))
        {
            possibleSolutions.remove(str);
        }
    }
}
4

4 に答える 4

8

Iterator( を使用するときに暗黙的に行うを開くと、を呼び出す以外for(String str: possibleSolutions)の基になるコレクション ( ) への変更により、が発生します。これは、コレクション クラスで非常に明確に文書化されています。possibleSolutionsremoveIteratorConcurrentModificationException

コレクションからアイテムを削除する必要がある場合は、明示的なIterator:

Iterator<String> it = possibleSolutions.iterator();
while(it.hasNext()) {
    if(compare(guess, it.next(), black1, white1))
        it.remove();
}

@allprog が指摘したように、このような明確な「フィルタリング」の問題がある場合は、機能的なアプローチが優れています。Java 8 がオプションになるまでは、Guava のIterables#filterorを使用するのIterables#removeIfがおそらく良い選択です。メソッドをラップしてcompare渡すだけです。

于 2013-09-10T20:25:09.383 に答える
2
/*
 * Shortens the list of possible solutions by eliminating everything that wouldn't get at least the given output.
 */
public void shortenTheList(String guess, int black1, int white1)
{
    for (String str : possibleSolutions)
    {
        if(compare(guess, str, black1, white1))
        {
            possibleSolutions.remove(str);
        }
    }
}

問題があります。

代わりに、次を使用します。

/*
 * Shortens the list of possible solutions by eliminating everything that wouldn't get at least the given output.
 */
public void shortenTheList(String guess, int black1, int white1)
{
    Iterator<String> it = possibleSolutions.iterator();
    while(it.hasNext())
    {
        String str = it.next();
        if(compare(guess, str, black1, white1))
        {
            it.remove();
        }
    }
}

これは、現在反復処理中のコレクションからオブジェクトを削除する唯一のクリーンな方法です。もう 1 つのあまり洗練されていない方法は、 の別Stringのリストを作成して削除し、それを反復処理することです。

于 2013-09-10T20:28:09.747 に答える
1

foreach ループを使用して反復処理を行っている間は、 possibleSolutionsリストを変更できません。

コードを次のように変更します。

public void shortenTheList(String guess, int black1, int white1)
{    
    for(Iterator<String> it = possibleSolutions.iterator(); it.hasNext()){
        String str = it.next();
        if(compare(guess, str, black1, white1)){
            it.remove();
        }
    }
}
于 2013-09-10T20:28:22.077 に答える