[gml]switch (foobar) {
case 1:
show_message("La variable vale 1.");
break;
case 2:
show_message("La variable vale 2.");
break;
case "foo":
show_message('La variable tiene el valor "foo".');
break;
}[/gml]
El valor de la expresi?n que le pases al switch (en este caso una variable llamada foobar) se compara con el valor de cada case, y si hay una coincidencia, se ejecuta el c?digo que precede al case hasta el break.
El c?digo anterior es equivalente a este:
[gml]if (variable == 1) {
show_message("La variable vale 1.");
}
if (variable == 2) {
show_message("La variable vale 2.");
}
if (variable == "foo") {
show_message('La variable tiene el valor "foo".');
}[/gml]
El switch tambi?n cuenta con un "case" especial llamado default:
[gml]switch (variable) {
case 1:
show_message("La variable vale 1.");
break;
case 2:
show_message("La variable vale 2.");
break;
case "foo":
show_message('La variable tiene el valor "foo".');
break;
default:
show_message("La variable tiene otro valor.");
break;
}[/gml]
El c?digo de default se ejecuta si ninguno de los anteriores cases se ejecut? (es decir que la variable no vale 1 ni 2 ni "foo").
La ventaja del switch es que s?lo ten?s que escribir la expresi?n a evaluar una vez.
Otra ventaja se puede apreciar considerando el siguiente switch:
[gml]switch (sprite_get_width(other.sprite_index)) {
case 10:
foo();
break;
case 20:
bar();
break;
default:
baz();
break;
}[/gml]
Ese c?digo, usando ifs ser?a as?:
[gml]if (sprite_get_width(other.sprite_index) == 10) {
foo();
} else if (sprite_get_width(other.sprite_index) == 20) {
bar();
} else {
baz();
}[/gml]
Ese c?digo es peor porque:
a) Es m?s repetitivo.
b) Es menos legible.
c) En un switch, la expresi?n solo se eval?a una vez. Usando ifs, si la primera condici?n es falsa, la funci?n sprite_get_width se vuelve a llamar. Por lo tanto el c?digo est? menos optimizado. Una posible soluci?n ser?a:
[gml]var tmp = sprite_get_width(other.sprite_index);
if (tmp = 10) {
foo();
} else if (tmp = 20) {
bar();
} else {
baz();
}[/gml]
Ah? la funci?n solo se llama una vez, pero se consume m?s memoria al guardar el valor devuelto en una variable, y el c?digo sigue siendo m?s lento.
En fin, el punto es que en algunas situalciones, el switch es la mejor opci?n ;).
Y una cosa m?s. Esto es una particularidad de C/C++, y no s? si se encuentra tambi?n en GML, pero me parece que s?, y a?n si no lo est?, me parece importante mencionarlo.
Consideramos el siguiente switch:
[gml]switch (5) {
case 1:
foo(); // Esto no se ejecuta.
break;
case 5:
bar(); // Esto se ejecuta.
case 10:
baz(); // Esto tambi?n (!!!).
break;
case 11:
game_end(); // Esto no.
break;
}[/gml]
La expresi?n a evaluar de ese switch es 5. Primero la compara con 1. 5 no es igual a 1, por lo tanto salta al siguiente case. El siguiente case es 5, y 5 es igual a 5, por lo tanto lo ejecuta. Luego, uno pensar?a que el int?rprete se sale del switch y comienza a ejecutar lo que sea que viene luego, pero el int?rprete no se sale del switch hasta no encontrarse con un break, por lo que el case 10 tambi?n se ejecuta por completo.
Es algo a tener en cuenta. En parte porque puede ser ?til, pero m?s que nada porque puede generar grandes bugs dif?ciles de encontrar, o puede ir acumulando bugs peque?os que hacen que el juego poco a poco y solo a veces, comience a funcionar mal. Esos bugs s? que son jodidos, y muy dif?ciles de localizar.
El est?ndar de C++ recomienda (y es una buena pr?ctica hacerlo en GML tambi?n) que cuando se cree un case sin break a prop?sito, se coloque un comentario que lo indique. Algo as?:
[gml]switch (5) {
case 1:
foo();
break;
case 5:
bar();
// Sin break.
case 10:
baz();
break;
case 11:
game_end();
break;
}[/gml]
Y eso es todo. Espero haber sido claro ;).
case 1:
show_message("La variable vale 1.");
break;
case 2:
show_message("La variable vale 2.");
break;
case "foo":
show_message('La variable tiene el valor "foo".');
break;
}[/gml]
El valor de la expresi?n que le pases al switch (en este caso una variable llamada foobar) se compara con el valor de cada case, y si hay una coincidencia, se ejecuta el c?digo que precede al case hasta el break.
El c?digo anterior es equivalente a este:
[gml]if (variable == 1) {
show_message("La variable vale 1.");
}
if (variable == 2) {
show_message("La variable vale 2.");
}
if (variable == "foo") {
show_message('La variable tiene el valor "foo".');
}[/gml]
El switch tambi?n cuenta con un "case" especial llamado default:
[gml]switch (variable) {
case 1:
show_message("La variable vale 1.");
break;
case 2:
show_message("La variable vale 2.");
break;
case "foo":
show_message('La variable tiene el valor "foo".');
break;
default:
show_message("La variable tiene otro valor.");
break;
}[/gml]
El c?digo de default se ejecuta si ninguno de los anteriores cases se ejecut? (es decir que la variable no vale 1 ni 2 ni "foo").
La ventaja del switch es que s?lo ten?s que escribir la expresi?n a evaluar una vez.
Otra ventaja se puede apreciar considerando el siguiente switch:
[gml]switch (sprite_get_width(other.sprite_index)) {
case 10:
foo();
break;
case 20:
bar();
break;
default:
baz();
break;
}[/gml]
Ese c?digo, usando ifs ser?a as?:
[gml]if (sprite_get_width(other.sprite_index) == 10) {
foo();
} else if (sprite_get_width(other.sprite_index) == 20) {
bar();
} else {
baz();
}[/gml]
Ese c?digo es peor porque:
a) Es m?s repetitivo.
b) Es menos legible.
c) En un switch, la expresi?n solo se eval?a una vez. Usando ifs, si la primera condici?n es falsa, la funci?n sprite_get_width se vuelve a llamar. Por lo tanto el c?digo est? menos optimizado. Una posible soluci?n ser?a:
[gml]var tmp = sprite_get_width(other.sprite_index);
if (tmp = 10) {
foo();
} else if (tmp = 20) {
bar();
} else {
baz();
}[/gml]
Ah? la funci?n solo se llama una vez, pero se consume m?s memoria al guardar el valor devuelto en una variable, y el c?digo sigue siendo m?s lento.
En fin, el punto es que en algunas situalciones, el switch es la mejor opci?n ;).
Y una cosa m?s. Esto es una particularidad de C/C++, y no s? si se encuentra tambi?n en GML, pero me parece que s?, y a?n si no lo est?, me parece importante mencionarlo.
Consideramos el siguiente switch:
[gml]switch (5) {
case 1:
foo(); // Esto no se ejecuta.
break;
case 5:
bar(); // Esto se ejecuta.
case 10:
baz(); // Esto tambi?n (!!!).
break;
case 11:
game_end(); // Esto no.
break;
}[/gml]
La expresi?n a evaluar de ese switch es 5. Primero la compara con 1. 5 no es igual a 1, por lo tanto salta al siguiente case. El siguiente case es 5, y 5 es igual a 5, por lo tanto lo ejecuta. Luego, uno pensar?a que el int?rprete se sale del switch y comienza a ejecutar lo que sea que viene luego, pero el int?rprete no se sale del switch hasta no encontrarse con un break, por lo que el case 10 tambi?n se ejecuta por completo.
Es algo a tener en cuenta. En parte porque puede ser ?til, pero m?s que nada porque puede generar grandes bugs dif?ciles de encontrar, o puede ir acumulando bugs peque?os que hacen que el juego poco a poco y solo a veces, comience a funcionar mal. Esos bugs s? que son jodidos, y muy dif?ciles de localizar.
El est?ndar de C++ recomienda (y es una buena pr?ctica hacerlo en GML tambi?n) que cuando se cree un case sin break a prop?sito, se coloque un comentario que lo indique. Algo as?:
[gml]switch (5) {
case 1:
foo();
break;
case 5:
bar();
// Sin break.
case 10:
baz();
break;
case 11:
game_end();
break;
}[/gml]
Y eso es todo. Espero haber sido claro ;).