【问题标题】:Try/catch in a game loop在游戏循环中尝试/捕捉
【发布时间】:2018-09-22 23:19:10
【问题描述】:

我有这个小猜谜游戏代码。为了处理字符串输入,我使用了 try/catch 块。 Try 工作得很好,但是 catch-block 在循环之外,我似乎无法让它在里面工作。所以程序在捕获异常后停止。我应该怎么做才能让我的循环在捕获异常后继续?

fun main(args: Array<String>) {

    val rand = java.util.Random()
    val n = 1 + rand.nextInt(100)
    var guess: Int
    var numberOfTries = 0

    println("I guessed a number from 1 до 100. What is it?\n")

    try {
        do {
            guess = readLine()!!.toInt()
            var x = Math.abs(n - guess)
            numberOfTries++

            when (x) {
                in 1..3 -> println("А-а-аh! It's burning!")
                in 4..7 -> println("Really hot!")
                in 8..15 -> println("Warm")
                in 16..31 -> println("A bit warm!")
                in 32..63 -> println("Pretty cold")
                in 64..99 -> println("It's freezing!")

            }

        } while (guess != n)

    } catch (e: NumberFormatException) {
        println("Use digits, please!") }

    println("Wow! You only used $numberOfTries tries!")
}

【问题讨论】:

    标签: loops kotlin try-catch


    【解决方案1】:

    正如 MFazio23 提到的,您在 while 循环中使用 try。否则,如果抛出异常,它将退出循环。

    如果抛出异常,则内部的任何内容都会停止,其中包括更多代码。如果你有一个抛出异常的方法,它之后的代码将不会被执行。 try-catch 为异常创建一个入口点;您的代码将在相关的 catch 块内继续(如果没有,则退出程序),这意味着 try-catch 内的循环将停止。

    但是,您实际上根本不需要 try-catch。 Kotlin 有一个很好的扩展函数 toIntOrNull,它完全符合您的预期;它尝试将输入转换为 int,并返回数字,如果失败则返回 null。所以,你可以这样做:

    fun main(args: Array<String>) {
    
        val rand = java.util.Random()
        val n = 1 + rand.nextInt(100)
        var guess: Int?
        var numberOfTries = 0
    
        println("I guessed a number from 1 до 100. What is it?\n")
    
        do {
            guess = readLine()?.toIntOrNull() // Note that this now uses ?. instead of !!. This is to make the null check useful If it throws an NPE, it kinda defeats the point. If the line is null, it now prints the same message as an invalid number
            // numberOfTries++ // move this up here if you want to count invalid guesses as a guess
            if(guess == null){
                System.out.println("Only use numbers")
                continue;
            }
            val x = Math.abs(n - guess)// I also changed this to a val; it's immutable, so it doesn't need to be a var
            numberOfTries++
    
            when (x) {
                in 1..3 -> println("А-а-аh! It's burning!")
                in 4..7 -> println("Really hot!")
                in 8..15 -> println("Warm")
                in 16..31 -> println("A bit warm!")
                in 32..63 -> println("Pretty cold")
                in 64..99 -> println("It's freezing!")
            }
        } while (guess != n)
        println("Wow! You only used $numberOfTries tries!")
    
    }
    

    您还可以进一步优化它,但使用扩展函数/变量(我不确定它是什么,它是一个声明为扩展函数的变量,但由于也有一个 getter,我不确定要做什么叫它)叫absoluteValue

    您也可以使用 if 语句,但它比使用 this 稍微多一点样板。您不能使用 null 调用 Math.abs,因为它使用原语。 Java 中的基元永远不能为空。

    这意味着你传递给你的任何东西都不能为空,这在 Kotlin 中意味着一个实例 Int。如果它可以为空,则为Int?,但该方法需要来自 Kotlin 的非空值。你不能将Int? 传递给Int(你可以反过来,但这与这里无关)。

    在底层,.absoluteValue 调用 Math.abs(n),但由于它是一个调用,因此您可以使用 null 安全运算符 (?.)

    guess = readLine()?.toIntOrNull() 
    val x = guess?.absoluteValue
    numberOfTries++
    when (x) {
        in 1..3 -> println("А-а-аh! It's burning!")
        in 4..7 -> println("Really hot!")
        in 8..15 -> println("Warm")
        in 16..31 -> println("A bit warm!")
        in 32..63 -> println("Pretty cold")
        in 64..99 -> println("It's freezing!")
        null -> println("Please only use numbers")
    }
    

    现在x 可以为空,您可以将null 添加到when 语句(响应您的评论)。

    另外,如果您只希望numberOfTries 增加有效数字,请在调用之前添加if(x != null)

    【讨论】:

    • 效果很好。但是我们不能在 when 块中使用 Null 检查吗?比如当 (x) null -> println ("No!")
    • x 永远不会为空。此外,您不能将 null 传递给 Math.abs。不过有一个很小的解决方法。我只是更新我的答案,代码有点太长,无法在评论中发布。
    • yap,我注意到它不会让我这样做(n - 猜测),因为存在类型不匹配 int? vs Int 如果我不检查猜测是否为空
    • 编辑了答案。
    【解决方案2】:

    您应该能够在您的do...while 中添加try...catch 块。唯一需要的其他更改是用一个值初始化 guess(因为不能保证在命中 while 块之前设置它):

    val rand = java.util.Random()
    val n = 1 + rand.nextInt(100)
    var guess = 0
    var numberOfTries = 0
    
    println("I guessed a number from 1 до 100. What is it?\n")
    
    do {
        try {
                guess = readLine()!!.toInt()
                val x = Math.abs(n - guess)
                numberOfTries++
    
                when (x) {
                    in 1..3 -> println("А-а-аh! It's burning!")
                    in 4..7 -> println("Really hot!")
                    in 8..15 -> println("Warm")
                    in 16..31 -> println("A bit warm!")
                    in 32..63 -> println("Pretty cold")
                    in 64..99 -> println("It's freezing!")
    
                }
        } catch (e: NumberFormatException) {
            println("Use digits, please!")
        }
    } while (guess != n)
    
    println("Wow! You only used $numberOfTries tries!")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-10
      • 1970-01-01
      • 1970-01-01
      • 2011-08-07
      • 1970-01-01
      • 2020-04-02
      • 1970-01-01
      • 2014-01-21
      相关资源
      最近更新 更多