19. Ahorcado en modo texto
Antes de hacer que nuestro "juego de plataformas en modo texto" sea un poco más modular, descomponiéndolo en funciones, y ya que hemos empezado a manejar "arrays" y "structs", vamos a cambiar momentáneamente de juego para practicar el uso de "arrays" y de "cadenas de texto", creando un "juego del ahorcado".
La lógica básica del juego será la siguiente:
- El ordenador escoge una palabra al azar (de entre un conjunto prefijado)
- La palabra se muestra como una serie de guiones: ---- ----
- El usuario elige una letra
- Si la letra no es parte de la palabra, el jugador pierde un intento (de los ocho iniciales)
- Si la letra es parte de la palabra, el jugador no pierde ningún intento, y la letra se muestra como parte de la palabra oculta: --a- -a--
- Esta estructura se repite desde el punto 2, hasta que el usuario se queda sin intentos o adivina toda la palabra.
La apariencia debería ser algo como:
¿Cómo se puede conseguir? Algunas de esas tareas son simples, pero también hay alguna un poco más enrevesada:
- Para escoger una palabra al azar de entre varias, basta con guardarlas en un "array de strings" y escoger una de ellas con la ayuda de un "Random".
- Para mostrar la palabra como una serie de guiones (---- ----) podemos volcar de forma repetitiva en una nueva cadena de texto, recorriendo letra por letra, y añadiendo un espacio si la frase a adivinar contiene algún espacio, o añadiendo un punto en caso de que sea cualquier otra letra.
- Lo de que el usuario elija una letra debería ser trivial a estas alturas...
- Para ver si la letra no es parte de la palabra, podemos usar "IndexOf"
- Para ir añadiendo letras a la palabra oculta (--a- -a--), como en C# no se pueden modificar directamente letras de una cadena, podemos ir volcando a una nueva cadena, de forma parecida a lo que hicimos en el punto 2: en una cadena auxiliar vamos guardando las letras de la frase que estábamos mostrando en pantalla, o la letra indicada por el usuario en caso de que coincida.
- Finalmente, para saber el final de la partida: lo de que el usuario se quede sin intentos es fácil si estamos llevando un contador de errores; lo de si adivina toda la palabra tampoco es difícil: podemos comprobar si ya no quedan guiones en el texto que se muestra en pantalla, o si la palabra que había que adivinar coincide con ese texto que se muestra en pantalla.
En forma de programa quedaría:
// Juego del ahorcado en modo texto using System; public class Ahorcado { public static void Main() { // 1: El ordenador escoge una palabra al azar (de entre un conjunto prefijado) string[] palabras = { "memento", "krull", "spiderman", "star wars", "hulk", "batman" }; Random generadorAleatorio = new Random(); int numeroAzar = generadorAleatorio.Next(0,palabras.Length); string palabraAdivinar = palabras[ numeroAzar ]; // 1b: La palabra se muestra como serie de guiones: ---- ---- string palabraMostrar = ""; for (int i=0; i< palabraAdivinar.Length; i++) if (palabraAdivinar[i] == ' ') palabraMostrar += " "; else palabraMostrar += "-"; // Otras variables int fallosRestantes = 8; char letraActual; bool terminado = false; // Parte repetitiva do { // 2: Se muestra la palabra oculta y el usuario elige una letra Console.WriteLine( "Palabra oculta: {0}", palabraMostrar); Console.WriteLine( "Fallos restantes: {0}", fallosRestantes); // 3: El usuario elige una letra Console.Write( "Introduzca una letra: "); letraActual = Convert.ToChar( Console.ReadLine() ); // 4: Si la letra no es parte de la palabra, el jugador // pierde un intento (de los ocho iniciales) if( palabraAdivinar.IndexOf( letraActual ) == -1 ) fallosRestantes--; // 5: Si la letra es parte de la palabra, el jugador no // pierde ningún intento, y la letra se muestra como // parte de la palabra oculta: --a- -a-- string siguienteMostrar = ""; for( int i = 0; i < palabraAdivinar.Length; i++) { if( letraActual == palabraAdivinar[i] ) siguienteMostrar += letraActual; else siguienteMostrar += palabraMostrar[i]; } palabraMostrar = siguienteMostrar; // 6: Comprobar si ha terminado: si el usuario se queda sin intentos // o adivina toda la palabra. if( palabraMostrar.IndexOf("-") < 0 ) { Console.WriteLine("Felicidades, acertaste! ({0})", palabraAdivinar); terminado = true; } if( fallosRestantes == 0 ) { Console.WriteLine("Lo siento. Era {0}", palabraAdivinar); terminado = true; } Console.WriteLine(); } while ( ! terminado ); } }
Ejercicio propuesto: Haz que este juego se comporte correctamente aunque la palabra tenga letras en mayúsculas o minúsculas, y aunque el usuario introduzca las letras en mayúsculas o en minúsculas.
Nota: también se puede modificar un poco, para practicar el uso de cadenas modificables (StringBuilder) y de "foreach", de forma que el paso 5 queda simplificado:
// Juego del ahorcado en modo texto // (Version con "StringBuilder" y "foreach" using System; using System.Text; // Para "StringBuilder" public class Ahorcado { public static void Main() { // 1: El ordenador escoge una palabra al azar (de entre un conjunto prefijado) string[] palabras = { "memento", "krull", "spiderman", "star wars", "hulk", "batman" }; Random generadorAleatorio = new Random(); int numeroAzar = generadorAleatorio.Next(0,palabras.Length); string palabraAdivinar = palabras[ numeroAzar ]; // 1b: La palabra se muestra como serie de guiones: ---- ---- StringBuilder palabraMostrar = new StringBuilder(); foreach (char letra in palabraAdivinar) if (letra == ' ') palabraMostrar.Append(" "); else palabraMostrar.Append("-"); // Otras variables int fallosRestantes = 8; char letraActual; bool terminado = false; // Parte repetitiva do { // 2: Se muestra la palabra oculta y el usuario elige una letra Console.WriteLine( "Palabra oculta: {0}", palabraMostrar); Console.WriteLine( "Fallos restantes: {0}", fallosRestantes); // 3: El usuario elige una letra Console.Write( "Introduzca una letra: "); letraActual = Convert.ToChar( Console.ReadLine() ); // 4: Si la letra no es parte de la palabra, el jugador // pierde un intento (de los ocho iniciales) if( palabraAdivinar.IndexOf( letraActual ) == -1 ) fallosRestantes--; // 5: Si la letra es parte de la palabra, el jugador no // pierde ningún intento, y la letra se muestra como // parte de la palabra oculta: --a- -a-- for( int i = 0; i < palabraAdivinar.Length; i++) if( letraActual == palabraAdivinar[i] ) palabraMostrar[i]= letraActual; // 6: Comprobar si ha terminado: si el usuario se queda sin intentos // o adivina toda la palabra. if( palabraMostrar.ToString().IndexOf("-") < 0 ) { Console.WriteLine("Felicidades, acertaste! ({0})", palabraAdivinar); terminado = true; } if( fallosRestantes == 0 ) { Console.WriteLine("Lo siento. Era {0}", palabraAdivinar); terminado = true; } Console.WriteLine(); } while ( ! terminado ); } }