Попробуйте / поймайте в игровой цикл - PullRequest
0 голосов
/ 20 сентября 2018

У меня есть небольшой код для игры в догадки.Чтобы разобраться со строковым вводом, я использовал блоки 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!")
}

Ответы [ 2 ]

0 голосов
/ 20 сентября 2018

Как упоминалось в MFazio23, вы используете try внутри цикла while.В противном случае он выйдет из цикла, если возникнет исключение.

Если выдается исключение, все, что находится внутри, останавливается, что включает в себя дополнительный код.если у вас есть метод, который выбрасывает исключение, ни один код после него не будет выполнен.Try-catch создает точку входа для исключения;Ваш код будет продолжен внутри соответствующего блока catch (или выйдет из программы, если его нет), что означает, что цикл внутри try-catch остановится.

Тем не менее, вам вообще не нужен трик-поймать.У Kotlin есть замечательная функция расширения под названием toIntOrNull, которая делает именно то, что вы ожидаете;он пытается преобразовать входные данные в int и возвращает число, или ноль, если это не удалось.Итак, вы можете сделать это:

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!")

}

Вы также можете оптимизировать его дальше, но используя функцию / переменную расширения (я не уверен, что это, это переменная, объявленная как расширениефункция, но так как есть геттер тоже, я не уверен, как это назвать) называется absoluteValue.

Вы также можете использовать операторы if, но это немного более шаблонно, чем это.Вы не можете вызвать Math.abs с нулем, потому что он использует примитивы.Примитивы в Java никогда не могут быть нулевыми.

Что означает, что все, что вы передаете вам, метод не может быть нулевым, что в Kotlin означает для экземпляра Int.Если это nullable, это Int?, но метод требует ненулевого значения от Kotlin.Вы не можете передать Int? на Int (вы можете сделать это наоборот, но это здесь не актуально).

Под капотом .absoluteValue вызывает Math.abs(n), но так как этовызов, вы можете использовать нулевой безопасный оператор (?.)

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) перед вызовом.

0 голосов
/ 20 сентября 2018

Вы должны иметь возможность добавить блок try...catch прямо в ваш do...while.Единственное другое необходимое изменение - инициализация 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!")
...