Con las expresiones case, puedes controlar el flujo de un programa a partir de una lista de opciones. La instrucción `case` en Verse es una forma de probar un valor contra múltiples valores posibles (como si estuvieras usando =), y ejecutando código basado en el que coincide.
El uso de expresiones `case` puede encontrarse en todo tipo de aplicaciones, como en los juegos en los que hay un personaje no jugador (PNJ).
Por ejemplo, digamos que usas el dispositivo generador de guardias para generar un guardia con su opción de patrulla activada. Después de que el guardia aparezca en el juego, tiene varios estados activos posibles, como Inactivo, Patrulla, Alerta, Ataque y Recolección. Un diagrama de transición de estados de alto nivel para esto podría ser así:
Puedes observar estas transiciones de estado en el juego.
En este vídeo, el guardia tiene la opción de patrulla activada como el comportamiento predeterminado.
En el vídeo, el guardia pasa de patrullar la base científica a recolectar algunos recursos. A continuación, el guardia localiza al jugador, lo que hace que el guardia entre en estado de alerta (indicado por el signo de interrogación flotante) antes de entrar en su estado de ataque (indicado por el signo de exclamación flotante).
En función del estado en el que se encuentre el guardia, mostrará ciertos comportamientos, y estos comportamientos se codifican habitualmente como funciones que son llamadas cuando el programa elige entrar en un estado específico.
Como código, esta transición de estado de guardia de alto nivel podría tener este aspecto:
case(GuardStateVariable):
idle_state =>
RunIdleAnimation()
SearchPlayerCharacter()
harvest_state =>
GatherResources()
alert_state=>
RunAlertAnimation()
PlayAlertSound()
DisplayAlertUIElement()
Esta expresión case pasa a ser una etiqueta que indica al programa qué funciones debe ejecutar si el guardia entra en un estado específico.
En esta expresión, el patrol_state del guardia es el `case` predeterminado porque un guardia con la patrulla activada debería ejecutar su comportamiento de patrulla por defecto.
Sintácticamente, esto es lo mismo que:
expression0
case (test-arg-block):
label1 =>
expression1
label2 =>
expression2
_ =>
expression3 for the default case
expression4Cada patrón del bloque case, como label1 y label2, debe usar la forma constant => block, donde constant puede ser una constante integer, logic, string, char o enum. Así que las instrucciones `case` solo funcionan con int, logic, string, char y enumeradores.
Estructura
Estructuralmente, la expresión `case` de Verse ejecuta un código basado en la entrada del bloque de argumentos de prueba GuardStateVariable, y funcionalmente trabaja igual que una serie de expresiones if.
En este ejemplo, el programa Verse ejecuta expression3 si GuardStateVariable se resuelve como alert_state. Si el programa pasa en patrol_state, Verse salta estructuralmente al `case` predeterminado, y ejecuta expression5.
Uso de `case` con otro flujo de control
Los bloques de una instrucción `case` pueden romper y continuar si la instrucción `case` está en un loop. Los bloques de una instrucción `case` también pueden volver de la función en que se encuentran.
Por ejemplo:
loop:
case (x):
42 => break
_ => {}Esta repetición terminará inmediatamente si x = 42 o se repetirá eternamente.
Otro ejemplo:
Foo(x : int) : int =
case (x):
100 => return 200
_ => return 100Este ejemplo equivale a:
Foo(x : int) : int =
case (x):
100 => 200
_ => 100Esto ocurre porque la instrucción `case` es la última expresión de la función.
`case` predeterminado
Las instrucciones `case` que no tienen un `case` _=> predeterminado fallarán si ningún `case` coincide. Está bien utilizar estas instrucciones `case` en contextos de fallo (como las funciones con el efecto decides).
Las instrucciones `case` que coinciden con todos los casos de un enumerador serán no falibles si no tienen un `case` _=>.