【问题标题】:Checking for Winner in Connect Four - Kotlin在连接四中检查获胜者 - Kotlin
【发布时间】:2020-06-11 18:27:40
【问题描述】:

我正在使用 2D 数组在 Kotlin 中创建一个简单的 Connect Four 程序来打印电路板。除了我的水平 win-checker 功能外,一切正常。由于我使用的逻辑,在尝试将您的作品放在第一列时出现(索引超出范围)错误,因为它正在尝试检查数组中的下一列,但没有。有没有更好的方法来处理检查获胜者?这是我的功能:

fun checkWinsHorizontal() {
    for(row in 0 until gameBoard.size) {
        for(col in 0 until gameBoard.size){
            // if this spot is taken up by an "X", and the horizontally adjacent spaces are the same, declare winner
            if (gameBoard[row][col] == "X" && (gameBoard[row][col] == gameBoard[row][col - 1] && gameBoard[row][col] == gameBoard[row][col - 2] && gameBoard[row][col] == gameBoard[row][col - 3]) ){
                printBoard()
                println("YOU WIN")
                winner = true
                return
            }
            // same thing as above but for a "computer" opponent
            else if (gameBoard[row][col] == "O" && gameBoard[row][col] == gameBoard[row][col - 1] && gameBoard[row][col] == gameBoard[row][col - 2] && gameBoard[row][col] == gameBoard[row][col - 3]){
                printBoard()
                println("COMPUTER WINS")
                winner = true
                return
            }
        }
    }
}

【问题讨论】:

  • 索引超出范围是因为您遍历整个长度并且使用了前驱和后继。此外:算法应该只检查水平获胜条件还是垂直和对角线获胜条件?
  • 有几个选项。我可能会重构一下,但就目前而言,在外部循环中,您可以使用 ganeBoard[row][0] 的值初始化一个变量,然后在内部循环中将每个 gameBoard[row][col] 与该值进行比较价值。如果有任何不同,则退出循环,因为没有胜利。如果您到达内部循环的末尾,那么获胜者就是该变量中符号的所有者

标签: java kotlin indexoutofboundsexception 2d-games


【解决方案1】:

上面的 cmets 解释了为什么索引超出范围(您有硬编码值,例如 gameBoard[row][col - 1],但 col 可能为 0)。我建议一些修复:

首先,无需在每次移动后检查板上的每个单元格。玩家获胜的唯一方法是他们刚刚放置的棋子完成一行、一列或对角线。所以我建议你只检查涉及该单元的潜在胜利。

要为一行执行此操作,您可以使用以下内容:

fun completesRow(row: Int, col: Int) : Boolean {
  var count: Int = 1
  val symbol = gameBoard[row][col]
  // First move left - now we check that the symbols (X or O) match
  // AND that we're within bounds.
  var curCol = col - 1
  while (curCol >= 0 && gameBoard[row][curCol] == symbol) {
    ++count
    if (count == 4) {
        return true
    }
    --curCol
  }

  // same thing to the right; numColumns is assumed to be the number of
  // columns in the board.
  curCol = col + 1
  while (curCol < numColumns && gameBoard[row][curCol] == symbol) {
    ++count
    if (count == 4) {
        return true
    }
    ++curCol
  }

  // if you got here there weren't 4 in a row
  return false
}

注意:以上内容未经测试 - 我什至怀疑它是否可以编译,但希望它具有指导意义。

如果需要,您还可以进一步概括这一点。您可以为这些移动创建Iterator 实例,而不是使用向左/向右、向上/向下和对角线移动的不同函数,然后拥有一个需要 2 个迭代器(例如,一个向左移动一个向右移动)的函数,它可以使用它进行检查。这样您就可以使用相同的精确方法来检查水平、垂直或对角线的胜利。

【讨论】:

  • 您好,这非常有帮助,肯定会让我重回正轨,但我确实有一个小问题,因为我对布尔函数没有太多经验。似乎第二个 while 语句总是返回 true,你知道为什么会这样吗?
  • 当且仅当连续符号数为 4 表示有人赢得游戏时,两个 while 语句才返回 true。例如,假设col 右侧的符号与[row][col] 处的符号不匹配。然后while 语句应该退出而不返回true,并且你会在返回false 的函数末尾点击行。
  • 我刚刚注意到一个小错误并更新了代码 - count 应该初始化为 1 而不是 0,因为 [row][col] 处的单元格很重要。
  • 我知道当 count 等于 4 时,这两个语句应该返回 true。但是,第二个 while 语句一旦返回 true它被称为。
  • 我必须查看一些代码@Acuff558 才能理解为什么会发生这种情况。我也有兴趣了解您认为发生这种情况的原因(例如,您是否添加了一些打印语句或在调试器中运行它 - 换句话说,究竟有什么证据表明这种情况正在发生)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-22
  • 2019-05-10
  • 2020-10-20
  • 1970-01-01
相关资源
最近更新 更多