18. Presentación. Poder volver a jugar
Ahora mismo, cuando termina la partida, también termina todo el juego. Pero esto no es lo habitual: en un "juego real suele haber una pantalla de presentación previa, y tras terminar una partida se vuelve a esa pantalla de presentación y se puede comenzar una nueva partida.
Vamos a añadir esa posibilidad a nuestro juego...
No debería ser especialmente complicado:
- Ahora el "bucle de juego" (que representa el transcurso de una partida) deberá estar rodeado por un nuevo "do...while", que represente toda una sesión de juego.
- Antes de que comience el bucle de juego, se mostrará una pantalla que dé al usuario una serie de opciones (como mínimo, la de comenzar una nueva partida y la de abandonar el programa).
- Esa parte repetitiva debe incluir también las tareas que se deben volver a realizar cada vez antes de cada nueva "partida", como dejar las vidas en su valor inicial (3), los puntos también con su valor inicial (0), todos los premios visibles, volver a generar posiciones al azar para todos los elementos, etc.
// Primer mini-esqueleto de juego en modo texto // Versión "m" using System; using System.Threading; // Para Thread.Sleep public class Juego03m { struct ElemGrafico { public float x; public float y; public int xInicial; public int yInicial; public float incrX; public float incrY; public char simbolo; public ConsoleColor color; public bool visible; } public static void Main() { ElemGrafico personaje; personaje.xInicial = 40; personaje.yInicial = 12; personaje.x = personaje.xInicial; personaje.y = personaje.yInicial; personaje.simbolo = 'A'; personaje.color = ConsoleColor.Yellow; int numPremios = 10, numEnemigos = 10, numObstaculos = 20; // Reservo espacio para los datos repetitivos ElemGrafico[] obstaculos = new ElemGrafico[numObstaculos]; ElemGrafico[] enemigos = new ElemGrafico[numEnemigos]; ElemGrafico[] premios = new ElemGrafico[numPremios]; bool juegoTerminado = false; int vidas; int puntos; bool partidaTerminada; ConsoleKeyInfo tecla; // Tecla pulsada Random generador = new Random(); while (! juegoTerminado ) { // En cada partida, hay que reiniciar ciertas variables vidas = 3; puntos = 0; partidaTerminada = false; // Genero las posiciones de los elementos al azar for (int i=0; i<numObstaculos; i++) // Obstaculos { obstaculos[i].x = generador.Next(0,80); obstaculos[i].y = generador.Next(1,24); obstaculos[i].simbolo = 'o'; obstaculos[i].color = ConsoleColor.Red; } for (int i=0; i<numEnemigos; i++) // Enemigos { enemigos[i].x = generador.Next(0,80); enemigos[i].y = generador.Next(1,24); enemigos[i].incrX = 0.5f; enemigos[i].simbolo = '@'; enemigos[i].color = ConsoleColor.Blue; } for (int i=0; i<numPremios; i++) // Premios { premios[i].x = generador.Next(0,80); premios[i].y = generador.Next(1,24); premios[i].simbolo = '/'; premios[i].color = ConsoleColor.White; premios[i].visible = true; } // ---- Pantalla de presentación ---- Console.Clear(); Console.ForegroundColor = ConsoleColor.White; Console.SetCursorPosition(34,10); Console.Write("Jueguecillo"); Console.SetCursorPosition(31,12); Console.Write("Escoja una opción:"); Console.SetCursorPosition(15,17); Console.Write("1.- Jugar una partida"); Console.SetCursorPosition(15,19); Console.Write("0.- Salir "); tecla = Console.ReadKey(false); if (tecla.KeyChar == '0') { partidaTerminada = true; juegoTerminado = true; } // ------ Bucle de juego ------ while( ! partidaTerminada ) { // -- Dibujar -- Console.Clear(); // Marcador Console.Write("Vidas: {0} - Puntos {1}", vidas, puntos); for (int i=0; i<numObstaculos; i++) // Obstáculos { Console.SetCursorPosition( (int) obstaculos[i].x, (int) obstaculos[i].y); Console.ForegroundColor = obstaculos[i].color; Console.Write( obstaculos[i].simbolo ); } for (int i=0; i<numEnemigos; i++) // Enemigos { Console.SetCursorPosition( (int) enemigos[i].x, (int) enemigos[i].y); Console.ForegroundColor = enemigos[i].color; Console.Write( enemigos[i].simbolo ); } for (int i=0; i<numPremios; i++) // Premios { if (premios[i].visible) { Console.SetCursorPosition( (int) premios[i].x, (int) premios[i].y); Console.ForegroundColor = premios[i].color; Console.Write( premios[i].simbolo ); } } Console.SetCursorPosition( (int) personaje.x, (int) personaje.y); Console.ForegroundColor = personaje.color; Console.Write( personaje.simbolo ); // -- Leer teclas y calcular nueva posición -- if (Console.KeyAvailable) { tecla = Console.ReadKey(false); if(tecla.Key == ConsoleKey.RightArrow) personaje.x++; if(tecla.Key == ConsoleKey.LeftArrow) personaje.x--; if(tecla.Key == ConsoleKey.DownArrow) personaje.y++; if(tecla.Key == ConsoleKey.UpArrow) personaje.y--; } // -- Mover enemigos, entorno -- for (int i=0; i<numEnemigos; i++) // Enemigos { enemigos[i].x = enemigos[i].x + enemigos[i].incrX; if (( (int) enemigos[i].x == 0) || ( (int) enemigos[i].x == 79)) enemigos[i].incrX = - enemigos[i].incrX; } // -- Colisiones, perder vidas, etc -- for (int i=0; i<numObstaculos; i++) // Obstáculos { if ((obstaculos[i].x == personaje.x) && (obstaculos[i].y == personaje.y)) { vidas --; if (vidas == 0) partidaTerminada=true; personaje.x = personaje.xInicial; personaje.y = personaje.yInicial; } } for (int i=0; i<numPremios; i++) // Obstáculos { if ((premios[i].x == personaje.x) && (premios[i].y == personaje.y) && premios[i].visible ) { puntos += 10; premios[i].visible = false; } } for (int i=0; i<numEnemigos; i++) // Enemigos { if (( (int) enemigos[i].x == personaje.x) && ( (int) enemigos[i].y == personaje.y)) { vidas --; if (vidas == 0) partidaTerminada=true; personaje.x = personaje.xInicial; personaje.y = personaje.yInicial; } } // -- Pausa hasta el siguiente "fotograma" del juego -- Thread.Sleep(40); } // Fin del bucle de juego } // Fin de partida } // Fin de Main }
Ejercicio propuesto: Añade al menú una nueva opción que permita mostrar una ayuda al usuario, que le diga qué debe hacer en el juego (recoger premios, esquivar obstáculos y enemigos, etc).
Ejercicio propuesto (2): Añade una opción que "memorice" la puntuación más alta conseguida durante una sesión de juego (varias partidas consecutivas).