为什么我的 if-else 块没有被命中,尽管它应该被命中? (只需要另一双眼睛。)

发布于 2024-11-06 03:26:41 字数 1898 浏览 2 评论 0原文

我正在用 Java 制作一款落沙风格的游戏,但我的 if-else 块遇到了奇怪的问题。在我的 doGravity() 方法中,我有各种条件块,它们会导致不同的事情发生,并且由于某种奇怪的原因,一个块永远不会被击中。

当我用这个块计算每个条件被命中的次数时,左侧和右侧的块几乎均匀地被命中:

else if(world[x][y+1]==EMPTY && (x-1 >= 0) && world[x-1][y+1] == EMPTY && (x+1 < world.length) && world[x+1][y+1]==EMPTY) {
    int r = rand.nextInt(50);
    if(r == 0) {
        world[x-1][y+1] = world[x][y];
        //System.out.println("GO: right");
        countRight++;
    }
    else if(r == 1) {
        world[x+1][y+1] = world[x][y];
        //System.out.println("GO: left");
        countLeft++;
    }
    else {
        world[x][y+1] = world[x][y];
        countCenter++;
    }
    world[x][y] = EMPTY;
}

接下来是这个条件,它也均匀地分布在左侧和右侧。

else if((x-1 >= 0) && world[x-1][y+1] == EMPTY && (x+1 < world.length) && world[x+1][y+1]==EMPTY) {
    if(rand.nextBoolean()) {
        world[x-1][y+1] = world[x][y];
        //countLeft++;
    }
    else {
        world[x+1][y+1] = world[x][y];
        //countRight++;
    }
    world[x][y] = EMPTY;
}

但是当我计算这些块时,左侧的块永远不会被击中,即使左侧的空间打开。我觉得这可能只是一些愚蠢的错字,由于某种原因我看不到。

else if((x-1 >= 0) && world[x-1][y+1] == EMPTY) {
    world[x-1][y+1] = world[x][y];
    world[x][y] = EMPTY;
    countLeft++;
    System.out.println("Hit Left");
}
else if((x+1 < world.length) && world[x+1][y+1] == EMPTY) {
    world[x+1][y+1] = world[x][y];
    world[x][y] = EMPTY;
    countRight++;
    System.out.println("Hit Right");
}

更新:如果我在末尾注释掉left块,则绝对不会发生任何变化。沙子的作用完全相同。如果我在末尾注释掉 right 块,则其作用与注释掉两个块相同。我无法弄清楚这一点。它应该有效...但事实并非如此。

更新:这是完整的源代码。我不知道这可能是什么。事实上,它会让我发疯。 http://pastebin.com/mXCbCvmb

I am making a Falling Sand style game in Java, and I'm having weird issues with an if-else block that I have. In my doGravity() method, I have an various blocks of conditions that will cause different things to happen, and for some odd reason, one block is NEVER getting hit.

When I have this block count how many times each condition is hit, the left and right blocks are hit almost evenly:

else if(world[x][y+1]==EMPTY && (x-1 >= 0) && world[x-1][y+1] == EMPTY && (x+1 < world.length) && world[x+1][y+1]==EMPTY) {
    int r = rand.nextInt(50);
    if(r == 0) {
        world[x-1][y+1] = world[x][y];
        //System.out.println("GO: right");
        countRight++;
    }
    else if(r == 1) {
        world[x+1][y+1] = world[x][y];
        //System.out.println("GO: left");
        countLeft++;
    }
    else {
        world[x][y+1] = world[x][y];
        countCenter++;
    }
    world[x][y] = EMPTY;
}

Next comes this condition, which also equally distributes left and right.

else if((x-1 >= 0) && world[x-1][y+1] == EMPTY && (x+1 < world.length) && world[x+1][y+1]==EMPTY) {
    if(rand.nextBoolean()) {
        world[x-1][y+1] = world[x][y];
        //countLeft++;
    }
    else {
        world[x+1][y+1] = world[x][y];
        //countRight++;
    }
    world[x][y] = EMPTY;
}

But when I count these blocks, the left block NEVER gets hit, even when the space to the left is open. I feel like its probably just some stupid typo that I can't see for some reason.

else if((x-1 >= 0) && world[x-1][y+1] == EMPTY) {
    world[x-1][y+1] = world[x][y];
    world[x][y] = EMPTY;
    countLeft++;
    System.out.println("Hit Left");
}
else if((x+1 < world.length) && world[x+1][y+1] == EMPTY) {
    world[x+1][y+1] = world[x][y];
    world[x][y] = EMPTY;
    countRight++;
    System.out.println("Hit Right");
}

UPDATE: If I remark out the left block at the end, absolutely nothing changes. The sand acts exactly the same. If I remark out the right block at the end, it acts the same as if I remark out both blocks. I cannot figure this out. It should work... but it doesn't.

UPDATE: Here's the full source code. I have no idea what this could possibly be. It will, in fact, drive me insane. http://pastebin.com/mXCbCvmb

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

十年不长 2024-11-13 03:26:41

您的pastebin代码确实显示“Hit left”,您只需将世界的创建(第65行pastebin)更改为

    world = new Color[worldWidth][worldHeight+1];

因为我假设的y+1部分。除此之外,它向左和向右生长。

编辑: http://pastebin.com/GVmSzN4z 我用你的 doGravity 稍微调整了一下,让水滴更多一点对称。

Your pastebin code does show "Hit left", you just need to change the creation of world (line 65 pastebin) to

    world = new Color[worldWidth][worldHeight+1];

Because of the y+1 part i would suppose. Other than that it grows both to the left and to the right.

EDIT: http://pastebin.com/GVmSzN4z I twiddled a little with your doGravity to make the drops a little more symmetric.

从﹋此江山别 2024-11-13 03:26:41

我在发布的代码中没有看到任何奇怪的东西......但是第二个块开头的“else”让我认为可能在您希望由“left”处理的情况下执行上述条件案件。
该部分之前的 if 中的条件是什么?

编辑

在检查了完整的源代码后,我终于找到了问题所在。你的 doGravity 更新函数总是从左到右,这就引入了不对称性。通过改变它使得奇数/偶数扫描线的更新方向在左→右和右→左之间交替,不对称性消失。

private void doGravity() {
    for(int i = worldHeight - 1; i >= 0; i--) {
        if (i % 2 == 0)
        {
            for(int j = 0; j < worldWidth; j++) {
                if(world[j][i] != EMPTY) {
                    if(hasGravity(world[j][i])) {
                        dropParticle(j, i);
                    }
                }
            }
        } 
        else
        {
            for(int j = worldWidth-1; j >= 0; --j) {
                if(world[j][i] != EMPTY) {
                    if(hasGravity(world[j][i])) {
                        dropParticle(j, i);
                    }
                }
            }
        }
    }
}

I dont see anything strange in the posted code... however the "else" at the beginning of the second block makes me think that probably the above condition is being executed in cases that insted you would like to be handled by the "left" case.
What is the condition in the if before that part?

EDIT

After checking your full source code I finally found where the problem is. Your doGravity update function always goes left->right and this introduces the asymmetry. By changing it so that the update direction is alternating between left->right and right->left for odd/even scanlines the asymmetry disappears.

private void doGravity() {
    for(int i = worldHeight - 1; i >= 0; i--) {
        if (i % 2 == 0)
        {
            for(int j = 0; j < worldWidth; j++) {
                if(world[j][i] != EMPTY) {
                    if(hasGravity(world[j][i])) {
                        dropParticle(j, i);
                    }
                }
            }
        } 
        else
        {
            for(int j = worldWidth-1; j >= 0; --j) {
                if(world[j][i] != EMPTY) {
                    if(hasGravity(world[j][i])) {
                        dropParticle(j, i);
                    }
                }
            }
        }
    }
}
我做我的改变 2024-11-13 03:26:41

我从粘贴箱下载了你的代码,我做的第一件事就是提取这个方法并使用它而不是所有嵌入的数组单元格检查,这样我就可以设置一个断点并查看 x 和 < code>y 以及该索引单元格的内容是什么。

private boolean isEmpty(final int x, final int y)
{
    return world[x][y] == EMPTY;
}

我会将所有 EMPTY 检查提取为更具可读性的内容,例如 isLeftEmpty(x,y)isRightEmpty(x,y) 和 < code>isNextLeftEmpty(x,y) 它将帮助您推断代码中逻辑的正确性。

我还将 (x + 1 < world.length) 提取到 isNextXOutsideWorld(x),这将有助于记录您的意图并帮助推理您想要的逻辑以及。

这还有一个副作用,即简化 if/elseif/else 语句中的逻辑。

我进行了一些简短的调试,并让它运行了几分钟,得出的结论是以下行始终匹配并取代下一个 else if 语句。

else if ((x + 1 < world.length) && isEmpty(x + 1, y + 1) && 
         (x - 1 >= 0) && isEmpty(x - 1,y + 1))

当我运行它时总是正确的,所以它永远不会到达下一个语句,

else if ((x - 1 >= 0) && isEmpty(x - 1,y + 1))

我会尝试将每个 else/if 语句分解为具有描述性名称的方法调用,并且将所有这些语句按顺序使用策略 模式,因为它们都是互斥的。这么大的方法肯定是有代码味道的,再加上那些else/if块,臭味系数很高。

很难从 if/elseif/else 块中的所有噪音推断出您的预期行为。

I downloaded your code from paste bin the first thing I did was extract this method and use it instead of all the embedded array cell checking so I could set a break point and see what the values for x and y and what the contents of that indexed cell was.

private boolean isEmpty(final int x, final int y)
{
    return world[x][y] == EMPTY;
}

I would extract all the EMPTY checks to something more readable, such as isLeftEmpty(x,y) and isRightEmpty(x,y) and isNextLeftEmpty(x,y) it will help you reason about the correctness of your logic in your code.

I would also extract the (x + 1 < world.length) to isNextXOutsideWorld(x), this will help document your intentions and help with reasoning about the logic you intend as well.

This also has a side effect of simplifying the logic in the if/elseif/else statements.

I did some brief debugging and I let it run for a few minutes and came to the conclusion that the following line matches always and supersedes the next else if statement.

else if ((x + 1 < world.length) && isEmpty(x + 1, y + 1) && 
         (x - 1 >= 0) && isEmpty(x - 1,y + 1))

is always true when I run it, so it never reaches the next statement

else if ((x - 1 >= 0) && isEmpty(x - 1,y + 1))

I would try and break each of the else/if statements out to method calls with descriptive names and just all them all in order using a Strategy pattern since they are all mutually exclusive. That large of a method is definitely a code smell, compounded with all those else/if blocks, the stinky factor is high.

It is very hard to extrapolate what your intended behavior is from all the noise in the if/elseif/else blocks.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文