Cómo agregar un comportamiento condicional en Kotlin

1. Antes de comenzar

En este codelab de Kotlin, crearás otro juego de dados, Lucky Dice Roll, con el que se intentará lanzar un número de la suerte. El programa establecerá un número de la suerte y lanzará el dado. Luego, comparará el resultado del lanzamiento con el número de la suerte y, finalmente, mostrará un mensaje adecuado. Para lograr esto, aprenderás a comparar valores y a tomar decisiones diferentes en tu programa de Kotlin.

A fin de que puedas concentrarte en los conceptos de programación sin tener que preocuparte por la interfaz de usuario de la app, usarás la herramienta de programación de Kotlin basada en el navegador e imprimirás los resultados en la consola.

Requisitos previos

Qué aprenderás

  • Cómo usar las sentencias if y else
  • Cómo comparar valores mediante operadores como igual que (==), mayor que (>) y menor que (<)
  • Cómo usar las sentencias when a fin de elegir una opción según un valor determinado
  • Qué es el tipo de datos Boolean y cómo usar sus valores true y false para la toma de decisiones

Qué compilarás

  • Compilarás un juego de dados llamado Lucky Dice Roll, basado en Kotlin, que te permitirá especificar un número de la suerte. El jugador ganará si lanza ese número de la suerte.

Requisitos

  • Una computadora con conexión a Internet

2. La toma de decisiones dentro del código

El programa Lucky Dice Roll debe determinar si el usuario lanzó un número de la suerte y recibirá felicitaciones o, de no ser así, si verá un mensaje que lo invite a volver a intentarlo.

Como desarrollador de apps, tendrás que tomar decisiones acerca de cómo debe comportarse la app y crear diferentes resultados para los usuarios.

Si estás compilando una app de compra, puedes mostrar pantallas diferentes según las opciones de entrega que elija el usuario. En el caso de los juegos de preguntas y respuestas, debes mostrar pantallas diferentes en función de si la respuesta del jugador es correcta o no. Según la app, podría haber muchos resultados posibles, los que deberás tener en cuenta en tu código.

En tu programa Lucky Dice Roll, la app debería contemplar diferentes casos, como los siguientes:

  • Si el resultado del lanzamiento es el número de la suerte, muestra un mensaje de felicitaciones.
  • De lo contrario, si el resultado no es el número de la suerte, muestra un mensaje que invite a volver a intentarlo.

Para agregar esta lógica a tu código, usa palabras clave especiales de Kotlin, como if, else y when.

Veamos algunos ejemplos.

Usa una sentencia if a fin de establecer una condición que se cumplirá

  1. Revisa el código que aparece a continuación. ¿Puedes adivinar cuál será el resultado?
fun main() {
   val num = 5
   if (num > 4) {
       println("The variable is greater than 4")
   }
}
  1. Copia y pega el código en el editor de programa de Kotlin y ejecuta el programa para observar el resultado.
The variable is greater than 4

El proceso de toma de decisiones de este programa es el siguiente:

  1. Crea una variable num y establécela en 5.
  2. Si es verdadero que num es mayor que 4, imprime "The variable is greater than 4".
  3. En todas las demás situaciones, no hagas nada.

En el ejemplo anterior, num se estableció en 5. La sentencia if compara si la variable es mayor que 4. Como eso es verdadero, el sistema ejecutará las instrucciones indicadas en las llaves y, luego, imprimirá el mensaje.

Observa el formato general de la sentencia if:

  • Comienza con la palabra clave if.
  • Sigue con dos paréntesis (). Dentro de los paréntesis, coloca la condición. Esa condición indica todo lo que puede ser true o false. Por ejemplo, si un número es mayor que otro.
  • A continuación, agrega dos llaves {}. Dentro de ellas, coloca el código que se ejecutará si la condición es true.
if (condition-is-true) {
    execute-this-code
}

Usa una sentencia if para configurar una condición que no se cumplirá

  1. Cambia el valor de num a 3, como se muestra a continuación. ¿Qué esperas que suceda si ejecutas este código?
fun main() {
    val num = 3
    if (num > 4) {
        println("The variable is greater than 4")
    }
}
  1. Copia y pega el código en el editor de programa de Kotlin y ejecuta el programa para observar el resultado vacío.

Si se establece num en 3, no se imprimirá nada, ya que el valor de num es menor que 4. Por lo tanto, la condición de que num es mayor que 4 es false, el código entre las llaves no se ejecutará y no se imprimirá nada.

Usa else a fin de crear una alternativa para las condiciones que no se cumplen

En lugar de no hacer nada, puedes ofrecer a tus usuarios una alternativa cuando no se cumpla una condición. Como sucede con el lenguaje común, puedes hacer esto mediante una sentencia else.

  1. Agrega una sentencia else para imprimir un mensaje cuando num no sea superior a 4, como se muestra a continuación. ¿Qué esperas que suceda si ejecutas este código?
fun main() {
    val num = 3
    if (num > 4) {
        println("The variable is greater than 4")
    } else {
        println("The variable is less than 4")
    }
}
  1. Copia y pega el código en el editor de programa de Kotlin y ejecuta el programa para observar el resultado.
The variable is less than 4
  1. Ten en cuenta que, cuando num tenga un valor de 3, el programa imprimirá el mensaje "The variable is less than 4" asociado con la sentencia else, ya que num no es mayor que 4.
  2. Cambia num a 5 y vuelve a ejecutar el programa. Ahora es cierto que num es mayor que 4 y el programa imprimirá "The variable is greater than 4".
  3. Cambia num a 4 y ejecuta tu programa. Ahora 4 no es superior a 4, y el programa imprimirá "The variable is less than 4".

Si bien "The variable is less than 4" es el resultado correcto para las condiciones que estableciste en el código, ese enunciado impreso no es preciso, ya que 4 no es menor que 4. Lo que puedes hacer es agregar otra condición que compruebe la tercera posibilidad, es decir, si num es exactamente 4 y que, luego, imprima un enunciado correcto cuando esa condición resulte verdadera.

Usa una combinación de else y if para agregar condiciones alternativas

Puedes tener más de una condición. En el caso de ejemplo, esta es la forma de contemplar todas las posibilidades de num:

  • Si num es mayor que 4, imprime "The variable is greater than 4".
  • Sino, si num es igual a 4, imprime "The variable is equal to 4".
  • Sino, imprimir "The variable is less than 4".

A estos se los conoce como los casos diferentes de la sentencia if-else. Hay 3 casos detallados.

El código actualizado se verá de la siguiente manera:

fun main() {
    val num = 4
    if (num > 4) {
        println("The variable is greater than 4")
    } else if (num == 4) {
        println("The variable is equal to 4")
    } else {
        println("The variable is less than 4")
    }
}

Observa los cambios que se indican a continuación:

  • El valor de num ahora se establece en 4 a fin de que puedas probar la condición nueva.
  • Entre las sentencias if y else originales ahora existe una nueva sentencia else if para el caso cuando num sea exactamente 4.
  1. Copia y pega el código anterior en el editor de programa de Kotlin y ejecuta el programa para observar el resultado.
The variable is equal to 4
  1. Experimenta: cambia el valor de num y observa cómo esto afecta el resultado. Cambia num a 2 y 6 de modo que puedas ver que cada una de las condiciones aparece como true.

Flujo de control

A partir de las sentencias if-else anteriores, el código se ejecutará, o fluirá, según lo establecido por las condiciones. La manera de guiar la ejecución mediante estos condicionales se denomina el "flujo de control" del programa.

  • Supongamos que el num del lanzamiento del dado es 3. El programa verificará la primera condición (num > 4). Esto es falso, por lo que el programa verificará la siguiente condición (num == 4), que también es falso. Luego, el programa ejecutará el código de la sentencia else, que es la opción final.
  • Si el resultado del lanzamiento es 6, la primera condición (num > 4) será verdadera. El programa imprimirá el mensaje "The variable is greater than 4". Dado que esta condición es verdadera, no necesita comprobar el resto y no continuará con la sentencia if-else.
  • Usa otra combinación de if y else a fin de agregar condiciones alternativas.

3. Crea el juego Lucky Dice Roll

En esta sección, por medio del contenido que aprendiste en la tarea anterior, actualizarás el programa Lucky Dice Roll para comprobar si lanzaste un número de la suerte predeterminado. Si lo consigues, ¡ganas!

Configura tu código de partida

Estás iniciando el programa Lucky Dice Roll con un código similar al de la solución del programa Dice Roller anterior en Kotlin. Puedes editar la función main() de tu código anterior para que coincida, o bien copiar y pegar el código siguiente para comenzar.

fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    println("Your ${myFirstDice.numSides} sided dice rolled ${rollResult}!")
}

class Dice (val numSides: Int) {

    fun roll(): Int {
        return (1..numSides).random()
    }
}

Verifica si se lanzó el número de la suerte

Primero, establece el número de la suerte y, luego, compara el resultado del lanzamiento con ese número.

  1. En main(), borra la sentencia println().
  2. En main(), agrega un val llamado luckyNumber y establécelo en 4. Tu código debería verse de la siguiente manera:
fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4
}
  1. A continuación, agrega una sentencia if con una condición dentro de los paréntesis () que verifique si rollResult es igual (==) a luckyNumber. Deja espacio entre las llaves {} de modo que puedas agregar más código.
fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4
    if (rollResult == luckyNumber) {

    }
}
  1. Dentro de las llaves {}, agrega una sentencia println para imprimir "You win!"
fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4

    if (rollResult == luckyNumber) {
        println("You win!")
    }
}
  1. Ejecuta el programa. Quizás necesites ejecutarlo varias veces antes de tener suerte y ver el mensaje ganador en el resultado.
You win!

Muestra una respuesta cuando no se haya lanzado el número de la suerte

Si el programa no muestra ningún comentario al usuario cuando este no gana, es posible que el usuario se pregunte si el programa funciona. Te recomendamos que siempre proporciones una respuesta cuando el usuario realice alguna acción. En el programa Lucky Dice Roll, puedes indicarle que no ganó mediante una sentencia else.

  1. Agrega una sentencia else para imprimir "You didn't win, try again!".
fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4

    if (rollResult == luckyNumber) {
        println("You win!")
    } else {
        println("You didn't win, try again!")
    }
}
  1. Ejecuta el programa. Independientemente del resultado, el usuario siempre verá una notificación.

En este punto, el usuario sabrá si ganó o no, pero no conocerá el motivo. Siempre brinda información a los usuarios de modo que comprendan el resultado de sus acciones. Imagina que tu programa es una aplicación de préstamos. "La solicitud no fue aprobada porque tu calificación del crédito es baja" resulta mucho más informativo que "Lo sentimos, no podemos ofrecerte ningún préstamo. Vuelve a intentarlo". En el caso de Lucky Dice Roll, puedes dar un mensaje informativo diferente tras cada lanzamiento si el usuario no gana. Para lograr esto, usa varias sentencias else if.

  1. Agrega sentencias else if a fin de imprimir un mensaje diferente para cada lanzamiento. Si lo necesitas, consulta el formato que aprendiste en la tarea anterior.
fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4

    if (rollResult == luckyNumber) {
        println("You win!")
    } else if (rollResult == 1) {
        println("So sorry! You rolled a 1. Try again!")
    } else if (rollResult == 2) {
        println("Sadly, you rolled a 2. Try again!")
    } else if (rollResult == 3) {
        println("Unfortunately, you rolled a 3. Try again!")
    } else if (rollResult == 5) {
        println("Don't cry! You rolled a 5. Try again!")
    } else {
        println("Apologies! You rolled a 6. Try again!")
    }
}

Mediante el código anterior, el programa realiza las siguientes acciones:

  • Verifica si el rollResult es el luckyNumber.
  • Si el rollResult es el luckyNumber, imprime el mensaje ganador.
  • De lo contrario, comprueba si rollResult es 1 y, de ser así, imprime un mensaje que invita al usuario a intentarlo de nuevo.
  • De no ser así, comprueba si rollResult es 2 y, en ese caso, imprime un mensaje diferente para que el usuario vuelva a intentarlo.
  • Si tampoco se cumple esa condición, sigue realizando la validación hasta llegar al número 5.
  • Si el número lanzado no fue ninguno del 1 al 5, la única opción que queda es que sea el número 6, por lo que no es necesario que se realice otra prueba con else if. Puedes llegar a esa última posibilidad mediante la sentencia else final.

Dado que tener varios casos else if es algo muy frecuente, Kotlin tiene una manera más sencilla de escribirlos.

4. Usa una sentencia when

En programación, es muy común realizar pruebas de muchos resultados, o casos, diferentes. A veces, la lista de resultados posibles puede ser muy extensa. Por ejemplo, si lanzaras un dado de 12 caras, tendrías 11 sentencias else if entre el éxito y la else final. Para facilitar la escritura y lectura de este tipo de sentencias, lo cual ayuda a evitar errores, Kotlin ofrece una sentencia when.

Cambiarás tu programa de modo que use una sentencia when. Una sentencia when comienza con la palabra clave when, seguida de paréntesis (). Dentro de ellos, se indicará el valor que se va a probar. A continuación, se agregarán llaves {} a fin de que el código se ejecute en virtud de diferentes condiciones.

  1. En tu programa, en main(), selecciona el código desde la primera sentencia if hasta la llave } que cierra la última sentencia else y bórralo.
fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4
}
  1. En main(), debajo de la sentencia luckyNumber, crea una sentencia when. Dado que tu when debe realizar las pruebas con base en el resultado del lanzamiento, coloca rollResult entre los paréntesis (). Agrega llaves {} con espacios adicionales, como se muestra a continuación.
fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4

    when (rollResult) {

    }
}

Como antes, primero prueba si rollResult coincide con el luckyNumber.

  1. Dentro de las llaves {} de la sentencia when, agrega una sentencia que compare rollResult con luckyNumber y, si son iguales, que imprima el mensaje ganador. La sentencia se ve de la siguiente manera:
luckyNumber -> println("You win!")

Esto significa lo siguiente:

  • Primero, coloca el valor que estás comparando con rollResult. Es, decir, luckyNumber.
  • A continuación, ingresa una flecha (->).
  • Luego, agrega la acción que deseas que se realice en caso de haber una coincidencia.

Lee esto como "Si rollResult es luckyNumber, imprime el mensaje "You win!"".

Tu código main() tendrá el siguiente aspecto:

fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4

    when (rollResult) {
        luckyNumber -> println("You win!")
    }
}
  1. Usa el mismo patrón a fin de agregar líneas y mensajes para los posibles lanzamientos del 1 al 6 (excepto el 4), como se muestra a continuación. La función main() terminada debería verse de la siguiente manera:
fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4

    when (rollResult) {
        luckyNumber -> println("You won!")
        1 -> println("So sorry! You rolled a 1. Try again!")
        2 -> println("Sadly, you rolled a 2. Try again!")
        3 -> println("Unfortunately, you rolled a 3. Try again!")
        5 -> println("Don't cry! You rolled a 5. Try again!")
        6 -> println("Apologies! You rolled a 6. Try again!")
    }
}
  1. Ejecuta el programa. No hay diferencias en el resultado, pero tu código será mucho más compacto y fácil de leer.

¡Felicitaciones! Aprendiste dos formas de imprimir mensajes en función de una condición. Esta es una herramienta poderosa para escribir programas interesantes.

5. Código de solución

fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4

    when (rollResult) {
        luckyNumber -> println("You won!")
        1 -> println("So sorry! You rolled a 1. Try again!")
        2 -> println("Sadly, you rolled a 2. Try again!")
        3 -> println("Unfortunately, you rolled a 3. Try again!")
        5 -> println("Don't cry! You rolled a 5. Try again!")
        6 -> println("Apologies! You rolled a 6. Try again!")
   }
}

class Dice(val numSides: Int) {
    fun roll(): Int {
        return (1..numSides).random()
    }
}

6. Resumen

  • Usa una sentencia if a fin de establecer una condición para ejecutar algunas instrucciones. Por ejemplo, si el usuario lanza el número de la suerte, imprime un mensaje ganador.
  • El tipo de datos Boolean tiene valores true y false, y se puede usar para tomar decisiones.
  • Compara valores mediante operadores tales como igual que (==), mayor que (>) y menor que (<).
  • Usa una cadena de sentencias else if a fin de establecer varias condiciones. Por ejemplo, imprime un mensaje diferente para cada lanzamiento posible.
  • Usa una sentencia else al final de una cadena de condiciones a fin de detectar casos que pueden no estar contemplados de forma explícita. Si contemplas los casos para un dado de 6 caras, una sentencia else alcanzaría los números 7 y 8 lanzados con un dado de 8 caras.
  • Usa una sentencia when como una forma compacta de ejecutar código con base en la comparación de un valor.

Forma general de if-else:

if (condition-is-true) {
    execute-this-code
} else if (condition-is-true) {
    execute-this-code
} else {
    execute-this-code
}

Sentencia when:

when (variable) {
    matches-value -> execute-this-code
    matches-value -> execute-this-code
    ...
}

7. Más información

8. Practica por tu cuenta

Haz lo siguiente:

  1. Cambia myFirstDice para que tenga 8 caras y ejecuta tu código. ¿Qué ocurre entonces?

Sugerencia: Cuando aumentas la cantidad de caras, la sentencia when deja de contemplar todos los casos, por lo que no se imprimirá nada en los casos no contemplados.

  1. Corrige la sentencia when a fin de que tenga en cuenta las 8 caras. Puedes hacer esto si agregas los casos que correspondan a los números adicionales. Desafío: En lugar de agregar un caso nuevo para cada número, usa una sentencia else a fin de abarcar todos los casos que no están contemplados de forma explícita.

Sugerencia: Puedes agregar más casos para contemplar más caras. Esa es una buena forma de hacerlo si deseas un mensaje diferente para cada número posible. También puedes usar una sentencia else y, luego, imprimir el mismo mensaje para todas las caras mayores a las 6 contempladas en el código actual.

  1. Cambia myFirstDice para que tenga solo 4 caras. ¿Qué ocurre entonces?

Sugerencia: Cambiar la cantidad de caras de un dado por un número inferior al contemplado por la sentencia when no tiene un efecto evidente, ya que todos los casos posibles seguirán estando contemplados.