Using Kotlin, why does this code only work for 2 of the 3 possibilities?

When I run this on my phone, the button I tap only does 2 of the 3 possible things, and it changes depending on how I swap the order in the code. For example, usually the first option just doesn't do anything at all, but sometimes the first and last work, depending on how I rearrange the code. I have no idea what's going on. Here's my code that I'm using to do this.

    private fun changeScore() {
        when ((1..10).random()) {
            1 or 2 or 3 or 4 or 5-> win()
            6 ->  Toast.makeText(this, "neither", Toast.LENGTH_SHORT).show()
            7 or 8 or 9 or 10 -> loss()
        }
        balance.text = getString(R.string.score, coins.toString())
    }

    private fun loss() {
        coins --
        Toast.makeText(this, "loss", Toast.LENGTH_SHORT).show()
    }
    private fun win() {
        coins ++
        Toast.makeText(this, "win", Toast.LENGTH_SHORT).show()
    } 

when I tap the button, you should have a chance at loosing 1 coin or gaining 1 coin, and a 1 in 10 chance of nothing happening. Additionally, as a debug helper, all 3 options make a toast. Instead, one of the 3 options does nothing at all, no coins, and no toast. I've tried to just ignore the bug and rearrange it so the one that doesn't work is the one that only gives a toast, but I cant get that to work. How do I fix this so that all 3 are a possibility? Keep in mind, I only have less than a week of experience with Kotlin, so please explain things with that in mind because I'm relatively new to coding in general.


Solution 1:

You're not supposed to use or in when cases - it's operator for bitwise OR.

That means your 1 or 2 or 3 or 4 or 5 is equal to 7 and third case is 15. This caused your "anomaly" with what case was selected.

https://kotlinlang.org/docs/control-flow.html#when-expression explains how to properly make a switch you want:

when(i){
    in 1..5 -> win()   // use a range
    6 -> tie()
    7,8,9,10 -> loss()  // or separate values with commas
}

Solution 2:

If you want a when block to handle multiple conditions, you need to use commas to separate the arguments, not or

val i = 4
when(i) {
  4, 5 -> println("a") // will print "a"
  else -> println("b")
}

instead of

val i = 4
when(i) {
  4 or 5 -> println("a")
  else -> println("b") // will print "b"
}

If you want to better understand what the when is doing, you could expand out what it's doing in the or case like this

val i = 4
val j = 4 or 5
println("j = $j") // will print "j = 5"
when(i) {
  j -> println("a")
  else -> println("b") // will print "b"
}

The 4 or 5 statements gets evaluated as a single number, not a series of conditions.