通过列表迭代不检查每个对象

The*_*ark 1 c#

if (rowCount[i] >= 10)
{
    for (int j = 0; j < blocks.Count; j++)
    {
        if (blocks[j].Row == i)
        {
            blocks.RemoveAt(j);
            rowCount[i]--;
        }
    }
    foreach (Block b in blocks)
    {
        if (b.Row < i)
        {
            b.Row++;
            rowCount[b.Row]++;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

所以说我在阻止列表中有20个块.我经历了逐行调试的程序,我看到它没有检查列表中的每个块 - 它通常会留下4或5个未选中状态.我疯了还是有什么我想念的?

Eri*_*ert 10

对于公认的解决方案,更好的解决方案是以不同方式分解它.您希望在第一个循环中执行两项操作:减少rowcount[i]匹配数,并从列表中删除匹配的行.现在,如果没有任何循环,你会怎么做?第一个很简单:

rowCount[i] -= blocks.Where(block=>block.Row == i).Count();
Run Code Online (Sandbox Code Playgroud)

完成.第二个也很简单:

blocks.RemoveAll(block=>block.Row == i);
Run Code Online (Sandbox Code Playgroud)

两行代码.没有循环.显然是正确的.

如果你没有编写任何循环,那么你就不会在循环条件中出错.


Sco*_*ain 5

在循环时,您正在减小数组的大小,因此如果删除索引4,索引5将成为新索引4,您永远不会检查它.

修复它的两种方法是递减迭代器

if (rowCount[i] >= 10)
{
    for (int j = 0; j < blocks.Count; j++)
    {
        if (blocks[j].Row == i)
        {
            blocks.RemoveAt(j);
            rowCount[i]--;
            j--;
        }
    }
    foreach (Block b in blocks)
    {
        if (b.Row < i)
        {
            b.Row++;
            rowCount[b.Row]++;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

或以相反的顺序循环

if (rowCount[i] >= 10)
{
    for (int j = blocks.Count - 1; j >= 0; j--)
    {
        if (blocks[j].Row == i)
        {
            blocks.RemoveAt(j);
            rowCount[i]--;
        }
    }
    foreach (Block b in blocks)
    {
        if (b.Row < i)
        {
            b.Row++;
            rowCount[b.Row]++;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)