【问题标题】:For-loop iterates weirdlyFor循环奇怪地迭代
【发布时间】:2015-06-13 00:35:12
【问题描述】:

我正在写一段获胜者算法。这个为 Connect 4 赢得了垂直胜利,是的,有很多冗余和坏东西,至少我认为是这样,如果你愿意,让我知道哪些线不好,并提供建议,放置这些请在 cmets 部分。 顺便说一句,标签是否必要?我不知道。我把它扔在那里是因为我认为它可能会有所帮助。

我遇到了运行检查器一部分的 for 循环的问题。所以我决定发表一份印刷声明,看看发生了什么。这是我得到的:

2 /////// 1
3 /////// 2
4 /////// 1

请注意,棋盘上只有三个垂直排列且颜色相同的棋子。可以看到下面的打印语句结构:

public String verticalWin(RoundButton[][] useArray){
    //int a = 1;
    for(int row = 5; row > 2; row--){
        for(int col = 0; col < 7; col++){
            if(nextTileExists(row - 1, col) && !useArray[row][col].getBackground().equals(Color.YELLOW))
                if(useArray[row][col].getBackground().equals(useArray[row - 1][col].getBackground())){
                    comeHereLabel:
                    for(int a = 1; a < 4; a++){//THIS LOOP
                        if(nextTileExists(row - a, col))
                            if(useArray[row - a][col].getBackground().equals(useArray[row][col].getBackground())){
                                pieceWin++;
                                System.out.println(pieceWin + " /////// " + a);
                                if(pieceWin == 4)
                                    if(useArray[row][col].getBackground().equals(Color.RED))
                                        return "red";
                                    else
                                        return "black";
                            }
                                else
                                    break comeHereLabel;
                    }
                }
        }
    }

    return "A";
}

在方法的顶部,您可以看到我注释掉了int a = 1; 如果我取消注释该行,并转到标记为//THIS LOOP 的循环并将其更改为for(; a &lt; 4; a++) 代码的打印语句和操作彻底改变。我从新印刷中得到的是:

2 /////// 1
3 /////// 2
4 /////// 3

现在棋盘上实际上有 4 个棋子。 是什么导致了这种奇怪现象?

如果您需要更多代码或其他任何内容,请说出来。

【问题讨论】:

  • 因为for (int a = 1;...) 循环在另外两个for 循环中,所以它会被执行多次。您注释掉的代码顶部附近的int a = 1;a 的值设置为1 仅一次,以便完全执行您的方法。而每次您的内部 for 循环开始时,for (int a = 1; ...)a 设置为 1。
  • @JohnnyCoder 您的预期行为是什么?
  • 编码时,最好不要只在 b/c 中扔你认为可能有帮助的东西。您应该在使用它们之前查看在线文档和示例(有很多)以了解构造的行为方式。
  • @lurker,我做到了,并且觉得它可能会有所帮助,但我实际上并不确定。
  • @CNomad,预期的行为是我在左侧显示的第二个打印语句 2 3 4。

标签: java algorithm for-loop


【解决方案1】:

我强烈,强烈建议将您的程序拆分为函数。由于您只是在学习,让我们面对现实吧,Connect Four 不需要一流的性能,我建议:

public enum Result {
    kNone , kRed , kBlue
}
public RoundButton[] copyColumn ( RoundButton[][] board , int column )
{
    // return a new array with the items from the specified column
}
public RoundButton[] copyDiagonal ( RoundButton[][] board , int startRow,int startCol , int slope )
{
    // return a new array with items in the diagonal start at the specified location, either going up to the right or down to the right
}
public Result evaluate ( RoundButton[] array )
{
    // return whether or not any winners were found in this array
}
public Result evaluateBoard ( RoundButton[][] board )
{
    // Iterate through the columns & rows; if a winner is found: return it.
    for ( int row=0 ; row<6 ; ++row ) {
        Result r = evaluate ( board[row] ) ;
        if ( r != kNone ) return r ;
    }
    for ( int col=0 ; col<7 ; ++col ) {
        RoundButton[] column = copyColumn ( board , col ) ;
        Result r = evaluate ( column ) ;
        if ( r != kNone ) return r ;
    }

    // Iterate through the diagonals; if a winner is found: return it.
    // Assuming board[0][0] is the bottom left...
    // Only starting at rows [0,2] going up can have a winner
    for ( int row=0 ; row<=2 ; ++row ) {
        RoundButton[] diag = copyDiagonal ( board , row,0 , 1 ) ;
        Result r = evaluate ( diag ) ;
        if ( r != kNone ) return r ;
    }
    // Only starting at rows [3,5] going down can have a winner
    for ( int row=3 ; row<=5 ; ++row ) {
        RoundButton[] drag = copyDiagonal ( board , row,0 , -1 ) ;
        Result r = evaluate ( diag ) ;
        if ( r != kNone ) return r ;
    }
    // Only starting at cols [0,3] going up can have a winner
    // ... but we'll cover 0 in the rows section first
    for ( int col=1 ; col<=3 ; ++col ) {
        RoundButton[] drag = copyDiagonal ( board , 0,col , 1 ) ;
        Result r = evaluate ( diag ) ;
        if ( r != kNone ) return r ;
    }
    // Only starting at cols [0,3] going down can have a winner
    // ... but we'll cover 0 in the rows section first
    for ( int col=1 ; col<=3 ; ++col ) {
        RoundButton[] drag = copyDiagonal ( board , 5,col , -1 ) ;
        Result r = evaluate ( diag ) ;
        if ( r != kNone ) return r ;
    }

    return kNone ;
}

【讨论】:

  • 我很感激你的回答,我已经把它分解了。上面的方法只检查垂直,从代码寻找匹配片段的方向可以看出。但是,你能告诉我为什么int a = 1; 的放置会如此剧烈地影响输出吗?
  • 出于其他人所说的确切原因:当您在内部循环中定义它时,它每次都会得到集合。当您在循环之外定义它并且不重置它时,它不会被重置。仅用于检查垂直方向的代码很多;它的复杂性几乎不可避免地会导致错误或混乱。
  • 我知道代码很多。我不是算法专家,事实上这是我写的第一个,你应该看到这个的祖先,东西更长,只有一种颜色....
  • @JohnnyCoder 这可能与“int a”在整个函数期间没有重置有关。在第一种情况下,可能会调用中断并退出循环,重置“int a”
  • @CNomad,我明白了为什么它在 for 循环中使用 int a 时运行异常,但我仍然无法弄清楚为什么它在整个循环结构之外运行得这么好
【解决方案2】:

for 循环开始时,如果有第一个子句,它将执行它的第一个子句。

for(int a = 1; a < 4; a++) {
}

for(; a < 10; a++) {
    System.out.println(a);
}

此代码输出的第一件事是4,因为这将是完成第一个循环后a 的最后一个值。

for(a = 1; a < 20; a++) {
    System.out.println(a);
}

如果您随后执行此操作,第一个输出将是 1,因为 a 的值在迭代之前被重置。

【讨论】:

  • 等等,第一个循环如何打印 4?变量a是一个局部变量,所以a不会保留3的值,或者至少它不应该有正确的?
  • 在条件失败之前循环不会终止,直到 a 为 4 时条件才会失败。
  • 你在回答我关于你的第一个循环的问题吗?如果是这样,循环在 a = 3 之后终止...但不应保留该值,因为 a 是局部变量...
  • 是的。循环终止时 a 的值为 4。我目前没有要测试的编译器,但我假设 a 是包含方法的本地。
猜你喜欢
  • 2016-02-16
  • 1970-01-01
  • 2019-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-11
  • 2019-04-30
  • 2017-04-09
相关资源
最近更新 更多