0

I have this little guessing game code. In order to deal with the string input, I used try/catch blocks. Try works perfectly, but catch-block is outside of the loop and I can't seem to make it work inside. So the program stops after catching an exception. What should I do so that my loop continues after catching an exception?

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 Answers 2

2

As MFazio23 mentioned, you use the try inside the while loop. Otherwise, it will exit the loop if an exception is thrown.

If an exception is thrown, anything inside is halted, which includes further code. if you have a method that throws an exception, no code after it will be executed. The try-catch creates an entry-point for the exception; your code will continue inside the relevant catch block (or exit the program if there is none), which means the loop inside the try-catch will stop.

However, you actually don't need the try-catch at all. Kotlin has a nice extension function called toIntOrNull, which does exactly what you'd expect; it attempts to convert the input to an int, and returns the number, or null if it failed. So, you can do this:

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

}

You can also optimize it further, but using an extension function/variable (I'm not sure what it is, it's a variable declared as an extension function, but since there's a getter too, I'm not sure what to call it) called absoluteValue.

You could also use if-statements, but it is slightly more boilerplate than using this. You cannot call Math.abs with null, because it uses primitives. Primitives in Java can never be null.

Which means anything you pass you the method cannot be null, which in Kotlin means for an instance Int. If it's nullable, it's an Int?, but the method requires non-null from Kotlin. You can't pass Int? to Int (you can do it the other way around, but that's not relevant here).

Under the hood, .absoluteValue calls Math.abs(n), but since it's a call, you can use the null-safe operator (?.)

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

And now that x is nullable, you can add null to the when statement (in response to your comment).

Also, if you only want numberOfTries to increment on valid numbers, add an if(x != null) before you call it.

Sign up to request clarification or add additional context in comments.

2 Comments

It works nicely. But can't we use a Null check inside our when block? Like when (x) null -> println ("No!")
x is never null. Also, you can't pass null to Math.abs. There's a tiny workaround though. I'll just update my answer, the code is slightly too long to post in a comment.
1

You should be able to add the try...catch block right in your do...while. The only other change needed would be to initialize guess with a value (since it's not guaranteed to be set before the while block is hit):

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.