【问题标题】:Practice for breaking or returning in a loop练习循环中断或返回
【发布时间】:2014-01-08 09:34:01
【问题描述】:

背景:我正在做一个国际象棋游戏。它几乎可以完全工作,只是缺少对将死的检查,但我正在改进一些代码以提高可读性等。
现在,我正在重新编写一种方法,我必须检查从任何一块到板上另一个位置的路径。如果有一块挡住路径,则返回 true,如果没有,则返回 false。
注意:我不需要检查最后一个位置的位置,因为我的游戏会检查以确保您没有占据您要移动到的位置。

另外请注意,我已经研究过这个问题,我发现主要在这里的共识是打破是正确的解决方案。这比在循环外部初始化布尔变量并设置 true 或 false 并在该值上中断循环更可取。但是,我的循环中有两个条件可能使我的代码返回 true 或返回 false,所以我不能完全做到这一点。

当前代码

public boolean isPathClear(Location l1, Location l2) {

    int atx = l1.getX(); 
    int aty = l1.getY(); 
    int xdiff = 0, ydiff = 0;
    int endx = l2.getX(), endy = l2.getY();

    if(l1.getX() > l2.getX()) {
        xdiff = 1;
    }
    if(l1.getX() < l2.getX()) {
        xdiff = -1;
    }
    if(l1.getY() > l2.getY()) {
        ydiff = 1;
    }
    if(l1.getY() < l2.getY()) {
        ydiff = -1;
    }

while(true) {
        atx += xdiff; 
        aty += ydiff;

        if(atx == endx && aty == endy) {
            return true 
        }

        if(board[atx][aty].getType() != ' ') {
            return false; 
        }
    } 

问题:由于打破是首选方法,这就是我计划做的。但是,我遇到了一个问题,如果我在其中一个 if 语句中使用 break,看起来我必须在另一个中返回。喜欢:

while(true) {
        atx += xdiff; 
        aty += ydiff;

        if(atx == endx && aty == endy) {
            break;
        }

        if(board[atx][aty].getType() != ' ') {
            return false; 
        }
    }

    return true;

问题: 这似乎是一种可能令人困惑的混合。所以在我的情况下,这仍然是这段代码的首选方法吗:

boolean clear;

    while(true) {
        atx += xdiff; 
        aty += ydiff;

        if(atx == endx && aty == endy) {
            clear = true;
            break;
        }

        if(board[atx][aty].getType() != ' ') {
            clear = false;
            break;
        }
    }

    return clear;

【问题讨论】:

  • 我根本不会使用while (true),但我认为我是少数。 :-)
  • 你能展示你的整个方法吗?代码应该做什么?
  • 这里有一个关于整个主题的很好的讨论:programmers.stackexchange.com/questions/118703/…>
  • 我认为目标是一致性。我会做第一个或最后一个例子(第一个,我自己),但不是第二个。无论哪种方式,保持一致对读者更友好。
  • 对于具有挑战性的智力开发,请选择最短且最易读的。这可能意味着:回报。这样的讨论对于你推动产生美好而有智慧的东西来说是浪费时间和精力。

标签: java loops return conditional-statements break


【解决方案1】:

您可以尝试在while 循环中处理您的实际情况,而不是while(true),而您不需要额外的break 语句:

public boolean isPathClear(Location l1, Location l2) {
    int atx =  l1.getX(), aty =  l1.getY();
    int endx = l2.getX(), enxy = l2.getY();

    int xdiff = Integer.signum(endx - atx);
    int ydiff = Integer.signum(endy - aty);

    do{
        atx += xdiff;
        aty += ydiff;
    } while(!(atx == endx && aty == endy) && board[atx][aty].getType() == ' ');

    return atx == endx && aty == endy;
}

【讨论】:

  • 我无法使用?运算符在这种情况下,虽然该代码看起来非常好。它不起作用的原因是因为 xdiff 和 ydiff 可能为 0。如果移动是沿 x 轴或 y 轴而不是对角线,则其中一个将为 0。您可以为这种情况编写的最短代码是还有两个语句,例如int xdiff = atx &gt; 0 ? 0 : atx
  • 另外,你可以做 int xdiff = atx == endx 吗? 0: (atx > endx ? 1:-1);在一个单一的声明中,但它确实开始看起来令人费解。
  • 另外,我调整了 while 循环来处理 while() 中的两个条件。
  • 另外,我怀疑无论你如何实现这一点,你都希望将增量步骤更改为 'atx += atx == endx ? 0:xdiff'(对于 y 也是如此)来处理 x 和 y 不同时停止的情况。
  • 能否详细说明增量的变化?
【解决方案2】:

如果你想使用break 来做这件事 - 这并不重要 - 但我更喜欢这个:

boolean notObstructed = true;
while(notObstructed) {
    atx += xdiff; 
    aty += ydiff;
    if(atx == endx && aty == endy)
        break;
    if(board[atx][aty].getType() != ' ')
        notObstructed = false;
}
return notObstructed;

这样只有一个返回语句,其值是基于while循环和if语句配置的。

【讨论】:

    【解决方案3】:

    大多数情况下我会说这是一个主观的事情。

    上一个代码示例的一个客观优势是它为您提供了方法的单点退出,这对于调试通常很有用。我曾经与之共事的一位从事军事软件的人曾说过这是他们必须努力做到的要求:方法必须只有一个出口点。他声称这是一个健壮性/可靠性/可维护性的事情。我只是喜欢那种简单的“它就这样离开”的东西。

    【讨论】:

    • 仅仅因为一个要求是针对军事软件的,并不能说明这个要求是好的。或者它甚至是有道理的。
    • @Dodd10x:没有争论。不过,在这种情况下,我会说这是有充分理由的。
    • @Dodd10x,没有人说这是一个很好的要求。发帖人只是简单地指出,在这种情况下,一种风格可能有一个优势。
    • @MatthewC - TJ 已经扩展了他的答案,但我的意思只是说军方要求它并不正确。事实上,许多军事合同仍然需要瀑布式开发模型——我认为 stackoverflow 上的大多数人都会反对这一点。
    【解决方案4】:

    使用返回语句。这个想法是保持它的可读性和可维护性。只是不要在这些 if 语句中进行不同的方法调用,你会没事的。

    阅读 Bruce Eckel 的这篇文章:http://onthethought.blogspot.com/2004/12/multiple-return-statements.html

    使用 return 语句的另一个好处是其他程序员不太可能出现并修改您的局部变量,从而导致返回不正确的值。

    【讨论】:

      【解决方案5】:

      我更喜欢在这类循环中使用 return,因为我认为中断只是一种浪费。 在方法的末尾保留一个 return 语句,并在 if 语句中使用 2 个常规返回,它们将返回 true 或 false。

      最后我还记得编写了类似的代码,因为我的方法的返回类型是 void,我可以简单地使用:

      return;
      

      它会退出循环和方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-07-22
        • 1970-01-01
        • 2017-08-18
        • 1970-01-01
        • 2023-02-05
        • 2021-06-21
        • 1970-01-01
        相关资源
        最近更新 更多